Text and New Lines
Posted by Rob Camick on February 7, 2009
Files on different platforms represent a new line with different strings. For example, if I remember correctly, the new line strings are:
- “\r\n” – for Windows
- “\n” – for Unix
- “\r” – Macs (OS 9 and earlier)
- “\n” – Macs (OS X)
When you read a file into a Swing component the text is stored in a Document. To simplify Document processing the Swing developers decided that all new line strings would be represented by “\n” in the Document. Therefore, in Windows, the internal and external representation of a newline string is different. As long as you use the text component read() method to load the Document and the write() method to save the Document, this is not a problem. However, what happens when your program starts to query or use the text in the Document?
Most programmers will use the getText() method to get a string of text from the Document. What happens when you use this method on a Windows platform?
A JTextField only contains a single line of text so we don’t need to worry about it here.
When textArea.getText() is used on a JTextArea, the text will contain a “\n” for all newline strings contained in the Document. Therefore, you can’t just use this text and write it to a file using the write method of a Writer you created. If you do, you will be writing out different data to the file. That is, your file will now contain “\n” instead of “\r\n”. This explains why people have trouble reading files in Notepad when they are created in the above manner. The simple solution is to always use the text component write() methd.
When using textPane.getText() on a JTextPane, we have a different problem. In this case, the “\n” stored in the Document is replaced with “\r\n” in the text string. This now creates potential problems when using this string. For example, maybe you have a search function to highlight pieces of text in the text pane. So you search the text string to get the offset of the text and then you add a highlight to the text pane. The problem is that this offset will be wrong because the text string contains two characters for each newline, whereas the Document only has a single character for each newline. The highlighting will be off by 1, for every line in the file.
The solution in this case it to get the text string directly from the Document and not the text pane:
int length = textPane.getDocument().getLength();
String text = textPane.getDocument().getText(0, length);
In general, always use the read/write methods of the text component and you won’t have problems. Also be aware of the subtle difference in the getText() method when using Windows and a JTextPane.
End of Line String Property
When you use the read() method of a text component the DefaultEditorKit.EndOfLineStringProperty of the Document of the text component will be updated to reflect the end of line string found in the file. When you use the write() method of the text component the same end of line string will be used in the file.
When you use use the write() method to save text from a text component and the end of line string has not been set, then the write() method will use the string returned from System.getProperty(“line.separator”).
The EndOfLineString can be manually set by using: