javasystemwriter

Change line separator by programming


In Java, we use a BuffedWriter and the newline() method. Previously, you could change the character of the new line by changing the system property "Line.separator". Unfortunately, the Newline method seems to use System.LineSeparator() which is initialized at the very beginning from the "Line.separator" property. How can we change the character to use by the Newline() method, without changing newline() by the call of write()? We need to change it by programming. We cannot change the JVM argument, as the research program the line separator it must use.

It works in Java 1.8 and not in 11. We see nothing in Java's documentation that could prevent us from doing this.


Solution

  • This is a similar problem to How can I force Java stdout on windows to use the "\n" line seperator?.

    System.setProperty("line.separator","\n"); will not change System.lineSeparator(). Applying a system property change -Dline.separator= is not easy from some command lines but can be achieved by using java @file ... as in the other answer.

    On Windows you can save the line separator arguments to a file from CMD.EXE:

    echo -Dline.separator="\n"   > gnu.args
    echo -Dline.separator="\r\n" > windows.args
    

    On some bash you can use ANSI C quoting java -Dline.separator=$'\n' - see Setting Java VM line.separator.

    Ideally, declare your own BufferedWriter (or PrintWriter as in other answer) so that System property change is per use and does not affect the whole JVM:

    static BufferedWriter newLineWriter(Writer out, String lineSep) {
        return new BufferedWriter(out) {
            public void newLine() throws IOException {
                write(lineSep);
            }
        };
    }
    public static void main(String[] args) throws IOException {
        try(BufferedWriter out = newLineWriter(new FileWriter("unix.txt"), "\n")) {
            out.write("Line 1");
            out.newLine();
            out.write("Line 2");
        }
        try(BufferedWriter out = newLineWriter(new FileWriter("pc.txt"), "\r\n"))  {
            out.write("Line A");
            out.newLine();
            out.write("Line B");
        }
        try(BufferedWriter out = new BufferedWriter(new FileWriter("jvm.txt")))  {
            out.write("Line C");
            out.newLine();
            out.write("Line D");
        }
        System.out.println("Unix "+Arrays.toString(Files.readAllBytes(Path.of("unix.txt"))));
        System.out.println("PC   "+Arrays.toString(Files.readAllBytes(Path.of("pc.txt"))));
        System.out.println("JVM  "+Arrays.toString(Files.readAllBytes(Path.of("jvm.txt"))));
    }
    

    If you run the above with java @gnu.args ... it will show the line separator handling for each case:

    Unix [76, 105, 110, 101, 32, 49, 10, 76, 105, 110, 101, 32, 50]
    PC   [76, 105, 110, 101, 32, 65, 13, 10, 76, 105, 110, 101, 32, 66]
    JVM  [76, 105, 110, 101, 32, 67, 10, 76, 105, 110, 101, 32, 68]
    

    If you run the above with java @windows.args ... it will show:

    Unix [76, 105, 110, 101, 32, 49, 10, 76, 105, 110, 101, 32, 50]
    PC   [76, 105, 110, 101, 32, 65, 13, 10, 76, 105, 110, 101, 32, 66]
    JVM  [76, 105, 110, 101, 32, 67, 13, 10, 76, 105, 110, 101, 32, 68]