- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
最近引起我注意的是,Java 文本组件使用换行符(LF、\n
、0x0A)在内部表示和解释换行符。这让我感到非常惊讶,并提出了我的假设,即在问号下使用 System.getProperty('line.separator')
everywhere 是一个很好的做法。
似乎无论何时处理文本组件,在使用上述属性时都应该非常小心,因为如果使用 JTextComponent.setText(String)
,您最终可能会得到一个组件包含不可见的换行符(例如 CR)。这可能看起来并不那么重要,除非文本组件的内容可以保存到文件中。如果您使用所有文本组件提供的方法将文本保存并打开到一个文件中,那么您隐藏的换行符会在重新打开文件时突然出现在该组件中。原因似乎是 JTextComponent.read(...)
方法进行了规范化。
那么为什么 JTextComponent.setText(String)
不规范化行尾呢?或者任何其他允许在文本组件中修改文本的方法?在处理文本组件时使用 System.getProperty('line.separator')
是一种好的做法吗?这是一个好的做法吗?
一些代码可以正确看待这个问题:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TextAreaTest extends JFrame {
private JTextArea jtaInput;
private JScrollPane jscpInput;
private JButton jbSaveAndReopen;
public TextAreaTest() {
super();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Text Area Test");
GridBagLayout layout = new GridBagLayout();
setLayout(layout);
jtaInput = new JTextArea();
jtaInput.setText("Some text followed by a windows newline\r\n"
+ "and some more text.");
jscpInput = new JScrollPane(jtaInput);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0; constraints.gridy = 0;
constraints.gridwidth = 2;
constraints.weightx = 1.0; constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
add(jscpInput, constraints);
jbSaveAndReopen = new JButton(new SaveAndReopenAction());
constraints = new GridBagConstraints();
constraints.gridx = 1; constraints.gridy = 1;
constraints.anchor = GridBagConstraints.EAST;
constraints.insets = new Insets(5, 0, 2, 2);
add(jbSaveAndReopen, constraints);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TextAreaTest tat = new TextAreaTest();
tat.setVisible(true);
}
});
}
private class SaveAndReopenAction extends AbstractAction {
private File file = new File("text-area-test.txt");
public SaveAndReopenAction() {
super("Save and Re-open");
}
private void saveToFile()
throws UnsupportedEncodingException, FileNotFoundException,
IOException {
Writer writer = null;
try {
writer = new OutputStreamWriter(
new FileOutputStream(file), "UTF-8");
TextAreaTest.this.jtaInput.write(writer);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ex) {
}
}
}
}
private void openFile()
throws UnsupportedEncodingException, IOException {
Reader reader = null;
try {
reader = new InputStreamReader(
new FileInputStream(file), "UTF-8");
TextAreaTest.this.jtaInput.read(reader, file);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
}
}
}
}
public void actionPerformed(ActionEvent e) {
Throwable exc = null;
try {
saveToFile();
openFile();
} catch (UnsupportedEncodingException ex) {
exc = ex;
} catch (FileNotFoundException ex) {
exc = ex;
} catch (IOException ex) {
exc = ex;
}
if (exc != null) {
JOptionPane.showConfirmDialog(
TextAreaTest.this, exc.getMessage(), "An error occured",
JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
}
}
}
}
添加新文本行后该程序在我的 Windows 计算机上保存的内容的示例(为什么是单个 CR?o_O):
Edit01
我在 Netbeans IDE 中运行/调试了它,它在 Windows 7 上使用 JDK1.7u15 64 位 (C:\Program Files\Java\jdk1.7.0_15)。
最佳答案
首先,真正的答案是设计师认为设计应该如何运作。你真的需要问他们才能得到真正的原因。
话虽如此:
So why doesn't JTextComponent.setText(String) normalize line endings?
我认为最有可能的原因是:
这将是意想不到的行为。大多数程序员会期望1 文本字段上的“get”返回与“set”相同的字符串值……或用户输入的字符串值。
如果文本字段确实规范化,那么程序员将很难在需要的地方保留原始文本的行结尾。
设计者可能在某些时候想要改变他们的想法(参见报告的read
和write
方法的行为) 但出于兼容性原因无法做到这一点。
无论如何,如果您需要规范化,没有什么可以阻止您的代码对 setter 检索到的值执行此操作。
Or any other method that allows text to be modified within a text component for that matter?
据报道(见评论)read
和/或 write
进行规范化。
Is using System.getProperty('line.separator') a good practice when dealing with text components? Is it a good practice at all?
这取决于上下文。如果您知道您正在读写要在“这个”平台上处理的文件,这可能是个好主意。如果文件打算在不同的平台(使用不同的行分隔符)上读取,那么规范化以匹配当前机器的约定可能不是一个好主意。
1 - 事实上,read
和 write
等其他方法可能 的行为不同并不影响这一点。他们不是“getter”和“setter”。我说的是人们期望“getters”和“setters”如何表现……而不是其他任何东西。此外,人们不应该期望一切以同样的方式行事,除非指定他们这样做。但显然,这里的部分问题是规范......javadocs......对这些问题保持沉默。
另一种可能性是@predi 报告的规范化行为实际上发生在Reader
/Writer
对象中......
关于java - 为什么 JTextComponent.setText(String) 不规范化行结尾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17882554/
猫f1.txt阿曼维沙尔阿杰贾伊维杰拉胡尔曼尼什肖比特批评塔夫林现在输出应该符合上面给定的条件 最佳答案 您可以在文件读取循环中设置一个计数器并打印它, 计数=0 读取行时做 让我们数一数++ if
我正在尝试查找文件 1 和文件 2 中的共同行。如果公共(public)行存在,我想写入文件 2 中的行,否则打印文件 1 中的非公共(public)行。fin1 和 fin2 是这里的文件句柄。它读
我有这个 SQL 脚本: CREATE TABLE `table_1` ( `IDTable_1` int(11) NOT NULL, PRIMARY KEY (`IDTable_1`) );
我有 512 行要插入到数据库中。我想知道提交多个插入内容是否比提交一个大插入内容有任何优势。例如 1x 512 行插入 -- INSERT INTO mydb.mytable (id, phonen
如何从用户中选择user_id,SUB(row, row - 1),其中user_id=@userid我的表用户,id 为 1、3、4、10、11、23...(不是++) --id---------u
我曾尝试四处寻找解决此问题的最佳方法,但我找不到此类问题的任何先前示例。 我正在构建一个基于超本地化的互联网购物中心,该区域分为大约 3000 个区域。每个区域包含大约 300 个项目。它们是相似的项
preg_match('|phpVersion = (.*)\n|',$wampConfFileContents,$result); $phpVersion = str_replace('"','',
我正在尝试创建一个正则表达式,使用“搜索并替换全部”删除 200 个 txt 文件的第一行和最后 10 行 我尝试 (\s*^(\h*\S.*)){10} 删除包含的前 10 行空白,但效果不佳。 最
下面的代码从数据库中获取我需要的信息,但没有打印出所有信息。首先,我知道它从表中获取了所有正确的信息,因为我已经在 sql Developer 中尝试过查询。 public static void m
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我试图在两个表中插入记录,但出现异常。您能帮我解决这个问题吗? 首先我尝试了下面的代码。 await _testRepository.InsertAsync(test); await _xyzRepo
这个基本的 bootstrap CSS 显示 1 行 4 列: Text Text Text
如果我想从表中检索前 10 行,我将使用以下代码: SELECT * FROM Persons LIMIT 10 我想知道的是如何检索前 10 个结果之后的 10 个结果。 如果我在下面执行这段代码,
今天我开始使用 JexcelApi 并遇到了这个:当您尝试从特定位置获取元素时,不是像您通常期望的那样使用sheet.getCell(row,col),而是使用sheet.getCell(col,ro
我正在尝试在我的网站上开发一个用户个人资料系统,其中包含用户之前发布的 3 个帖子。我可以让它选择前 3 条记录,但它只会显示其中一条。我是不是因为凌晨 2 点就想编码而变得愚蠢? query($q)
我在互联网上寻找答案,但找不到任何答案。 (我可能问错了?)我有一个看起来像这样的表: 我一直在使用查询: SELECT title, date, SUM(money) FROM payments W
我有以下查询,我想从数据库中获取 100 个项目,但 host_id 多次出现在 urls 表中,我想每个 host_id 从该表中最多获取 10 个唯一行。 select * from urls j
我的数据库表中有超过 500 行具有特定日期。 查询特定日期的行。 select * from msgtable where cdate='18/07/2012' 这将返回 500 行。 如何逐行查询
我想使用 sed 从某一行开始打印 n 行、跳过 n 行、打印 n 行等,直到文本文件结束。例如在第 4 行声明,打印 5-9,跳过 10-14,打印 15-19 等 来自文件 1 2 3 4 5 6
我目前正在执行验证过程来检查用户的旧密码,但问题是我无法理解为什么我的查询返回零行,而预期它有 1 行。另一件事是,即使我不将密码文本转换为 md5,哈希密码仍然得到正确的答案,但我不知道为什么会发生
我是一名优秀的程序员,十分优秀!