Leepoint Java Reference Notes on the Java language and its standard library.

Platform-independent newlines

Windows uses two characters, Unix one. Mostly you should let the library decide.

Line endings differ: \n on Unix and macOS, \r\n on Windows. Writing \n into a file produces something Notepad historically showed as one long line.

Getting the right one

String nl = System.lineSeparator();

Or in a format string, which is usually tidier:

System.out.printf("Name: %s%n", name);      // %n, not \n

%n emits the platform separator. \n always emits one linefeed.

When you do not need to care

println appends the correct separator already. Building a string with \n and calling println on it is doing the job twice and getting it wrong once.

Files.write and Files.writeString with a list of lines insert the platform separator between them.

BufferedWriter.newLine() does the same.

So the explicit separator is needed mainly when assembling a multi-line string in memory:

String text = String.join(System.lineSeparator(), lines);

Reading is easier

Every sensible reader handles all three conventions — \n, \r\n and the old Mac \r — and strips them:

Files.readAllLines(path);
Files.lines(path);
reader.readLine();

None of these return the separator, so you do not have to trim it. Splitting a whole file on "\n" yourself does not handle \r\n, and leaves a trailing \r on every line — a bug that survives visual inspection and breaks string comparisons.

When to force one

Sometimes the format dictates the ending rather than the platform. HTTP headers and many network protocols require \r\n regardless of where the code runs. Some file formats specify \n. In those cases write the required bytes explicitly and ignore the platform — the requirement comes from the specification, not the machine.

That is the distinction worth keeping. Use System.lineSeparator() for text a local user will open in a local editor; use a literal when a specification tells you which one.

Git

Version control is where mixed endings become visible, usually as a diff touching every line of a file nobody edited. Setting core.autocrlf or committing a .gitattributes file settles it at the repository level, which is the right place — not in the code.