1. ホーム
  2. java

[解決済み] ファイルの内容からJavaの文字列を作成するにはどうすればよいですか?

2022-03-15 15:25:31

質問

以前から下のような慣用句を使っています。そして、少なくとも私が訪れたサイトでは、最も広く普及しているようです。

Javaでファイルを文字列に読み込むための、より良い/異なる方法はありますか?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}

解決方法は?

ファイルから全テキストを読み込む

Java 11 では readString() メソッドを使用して、小さなファイルを String 行の終端を保持する。

String content = Files.readString(path, StandardCharsets.US_ASCII);

Java 7 から 11 までのバージョンでは、コンパクトで堅牢なイディオムをユーティリティ・メソッドにまとめています。

static String readFile(String path, Charset encoding)
  throws IOException
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

ファイルからテキスト行を読み込む

Java 7では ファイルをテキスト行として読み取るための便利なメソッドです。 として表現されます。 List<String> . この方法は、各行の末尾からラインセパレータが取り除かれるため、quot;lossy"です。

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java 8 では Files.lines() メソッドで Stream<String> . この方法でも、行の区切り文字が取り除かれるため、損失が生じます。もし IOException が読み込まれた場合、そのファイルは UncheckedIOException というのは Stream はチェックされた例外を投げるラムダを受け入れない。

try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

これは Stream は必要ですが close() の呼び出しに気づかない人が多いのではないだろうか。 Stream には close() メソッドを使用します。必ず図のようにARM-blockを使用してください。

ファイル以外のソースを扱う場合は lines() メソッドを BufferedReader の代わりに

メモリ使用量

改行を維持する1番目の方法は、短時間にファイルの生の内容(バイト配列)とデコードされた文字(ファイルでは8ビットでエンコードされていてもそれぞれ16ビット)が一度にメモリに存在するため、一時的にファイルサイズの数倍のメモリを必要とすることがあります。使用可能なメモリに対して小さいと分かっているファイルに適用するのが最も安全です。

2番目の方法である行読みは、デコードのための入力バイトバッファにファイル全体を含める必要がないため、通常はよりメモリ効率が高くなります。しかし、利用可能なメモリに対して非常に大きなファイルにはまだ適していません。

大きなファイルを読むには、ストリームからテキストの塊を読み、それを処理し、同じ固定サイズのメモリブロックを再利用して次に進むという、別のデザインのプログラムが必要です。ここで、quot;large"はコンピュータのスペックに依存します。現在では、この閾値は何ギガバイトものRAMになるかもしれません。3つ目の方法は Stream<String> は、入力レコードが一行一行である場合の一つの方法である。(この場合 readLine() のメソッドです。 BufferedReader は、この方法に相当する手続き的なものです)。

文字エンコーディング

元の投稿にあるサンプルに欠けているものの1つは、文字エンコーディングです。プラットフォームのデフォルトが望ましいという特殊なケースもありますが、それは稀なことで、自分の選択を正当化できるようにする必要があります。

StandardCharsets クラスは、すべてのJavaランタイムに要求されるエンコーディングの定数を定義しています。

String content = readFile("test.txt", StandardCharsets.UTF_8);

プラットフォームのデフォルトは Charset クラス そのものである。

String content = readFile("test.txt", Charset.defaultCharset());


注:この回答は、私のJava 6バージョンを大きく置き換えたものです。Java 7のユーティリティは安全にコードを簡素化し、マップされたバイトバッファを使用する古い答えは、マップされたバッファがガベージコレクトされるまで、読み込まれたファイルが削除されることを防いでいました。旧バージョンはこの回答の "edited"のリンクから見ることができます。