読者です 読者をやめる 読者になる 読者になる

HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

改行コードの出力

改行コードがプラットフォームごとに異なるというのは常識だが、ついつい次のようなプログラムを書いてしまう。

System.out.printf("%5d %5d\n", 12, 345);

さすがに、print、printlnを使う場合はエスケープシーケンス "\n" を直接ソースコード上に書くことはないのだけど。

System.out.print("Hello World");
System.out.println();
System.out.println("Hello Java");

では、プラットフォームに依存しないようにしつつprintfで改行コードを出すかというと、次のように書く。

System.out.printf("%5d %5d%n", 12, 345);

エスケープシーケンス "\n" を使用せずに、フォーマット文字列 "%n" を使用する。

一応、どんな感じになるのかを試してみる。

package y2010.m02.d26.t001;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

public class Main {

    private static abstract class Proc {
        public abstract String getName();
        public abstract void proc(PrintStream out);
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        Proc[] procs = new Proc[] {
                new Proc() {
                    @Override
                    public String getName() {
                        return "printf(\"0000\\n\")";
                    }
                    @Override
                    public void proc(PrintStream out) {
                        out.printf("0000\n");
                    }
                },
                new Proc() {
                    @Override
                    public String getName() {
                        return "printf(\"0000\\r\\n\")";
                    }
                    @Override
                    public void proc(PrintStream out) {
                        out.printf("0000\r\n");
                    }
                },
                new Proc() {
                    @Override
                    public String getName() {
                        return "printf(\"0000\\r\")";
                    }
                    @Override
                    public void proc(PrintStream out) {
                        out.printf("0000\r");
                    }
                },
                new Proc() {
                    @Override
                    public String getName() {
                        return "printf(\"0000%n\")";
                    }
                    @Override
                    public void proc(PrintStream out) {
                        out.printf("0000%n");
                    }
                },
                new Proc() {
                    @Override
                    public String getName() {
                        return "println(\"0000\")";
                    }
                    @Override
                    public void proc(PrintStream out) {
                        out.println("0000");
                    }
                },
                new Proc() {
                    @Override
                    public String getName() {
                        return "line.separator";
                    }
                    @Override
                    public void proc(PrintStream out) {
                        out.print("0000" + System.getProperty("line.separator"));
                    }
                },
        };

        for (Proc p : procs) {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            PrintStream out = new PrintStream(bout);
            p.proc(out);
            out.flush();

            System.out.printf("%-24s  ", p.getName());
            byte[] array = bout.toByteArray();
            for (byte b : array) {
                System.out.printf(" %02x", b);
            }
            System.out.println();
        }
    }

}

Windows Vista での実行結果。

printf("0000\n")           30 30 30 30 0a
printf("0000\r\n")         30 30 30 30 0d 0a
printf("0000\r")           30 30 30 30 0d
printf("0000%n")           30 30 30 30 0d 0a
println("0000")            30 30 30 30 0d 0a
line.separator             30 30 30 30 0d 0a

Ubuntu 8.04 での実行結果。

printf("0000\n")           30 30 30 30 0a
printf("0000\r\n")         30 30 30 30 0d 0a
printf("0000\r")           30 30 30 30 0d
printf("0000%n")           30 30 30 30 0a
println("0000")            30 30 30 30 0a
line.separator             30 30 30 30 0a

最初の3つは書いたとおりにバイト列が生成される。残りの3つはプラットフォームごとに異なり、「System.getProperty("line.separator")」の内容に依存した出力となる。