Customizing line separator behavior in Java

CPColinSenior Java Architect
EE Senior Architect
Published:
Before I proceed, I should point out that I've always heard and used the term "line terminator" to refer to the characters that signify the end of a line of text, but the Java API documentation uses "line separator," so I've used that here, for consistency.

If you've ever run the same Java code on a Windows-based machine and a Unix- or Linux-based machine, you've probably noticed that lines of text don't always end the same way. Windows uses two characters: a carriage return (CR) and a line feed (LF). (Java uses '\r' and '\n' to represent these characters, respectively.) A good chunk of the rest of the world gets by with just an LF character ('\n'). Java does a pretty decent job of insulating developers from this distinction by having BufferedWriter.newLine() use whatever line separator is appropriate for the current operating system. (System.out.println(), by the way, typically is a call to PrintStream.println(), which calls BufferedWriter.newLine() behind the scenes.)

What if you need to override that behavior, though?

A few years ago, we at Experts Exchange ran into an issue with an internal tool where some of our machines were using Windows-style line separators and others were using the Unix-style. We needed a way to keep things consistent across platforms and had a few options open to us:
 
  • We could have overridden the line separator behavior for the entire JVM by specifying a value for the line.separator system property. We didn't want to do this, though, because it would have required making sure everybody was running the internal tool in the same, specific way. One person using the wrong command-line arguments would have sent us back to the drawing board.
  • We could have tried using System.setProperty() to set that property using code. This would have ensured some consistency, but there's a problem: the System.lineSeparator() method only ever returns what that property was when the JVM started—setting it later has no effect. Various bits of code could wind up using different line separators, depending on whether the value came from System.lineSeparator() or from System.getProperty("line.separator"). We didn't want to try to figure out what side effects that might have.

Ultimately, we picked an option that we knew wouldn't have any side effects: override the behavior in the instance of BufferedWriter we were using.
 
BufferedWriter writer = new BufferedWriter(outputStream)
                      {
                         /**
                          * Writes an LF character on all platforms, regardless of the value of the <code>line.separator</code> property.
                          */
                         @Override
                         public void newLine() throws IOException
                         {
                            write('\n');
                         }
                      };

Open in new window


This solution confined the custom behavior to the exact spot we needed it and kept everything running smoothly.
1
4,375 Views
CPColinSenior Java Architect
EE Senior Architect

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.