2016-02-05 17 views
6

特定の部分文字列を含むすべての行をテキストファイル内の別の文字列に置き換えるAPIを作成しようとしています。Stream-Java 8を使用してファイル内のテキストを置き換えます。

私は与えられたパターンが含まれている行をフィルタリングするには、Java 8のストリームを使用しています。ファイル書き込み部分に問題があります。上記のコード

Files.lines(targetFile).filter(line -> line.contains(plainTextPattern)).parallel() 
     .map(line-> line.replaceAll(plainTextPattern, replaceWith)).parallel(); 

は、ファイルの行単位で読み込み、パターンと一致する行をフィルタリングし、所与の文字列に置き換え、置き換えのみのラインを持っている文字列の流れをバック与えます。

これらの行をファイルに書き戻す必要があります。パイプラインが終了すると、我々は、ストリームを失うので、私は、パイプラインに以下を追加:

.forEach(line -> { 
try { 
      Files.write(targetFile, line.toString().getBytes()); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
私はそれがファイルのみ変更された(それがパイプラインにあるので)ラインに書き込み、他を続けるだろう期待していた

手つかずの線。

しかし、ファイル内の各行のファイルを切り捨て、最後に処理ラインを保つように見えるし、パイプラインで一致しなかったすべての行を削除します。

ストリームを使用してファイルを処理する方法がありますか?

+3

[ドキュメント](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#write-java。 nio.file.Path-byte:A-java.nio.file.OpenOption ...-): "デフォルトでは、メソッドは新しいファイルを作成するか、既存のファイルを上書きします。"ソリューションのために残りのドキュメントを読んでください。また、単に古いテキストファイルを変更することはできません。適切な変更を加えて新しいものを作成して置き換える必要があります。 – Pshemo

+0

ありがとう!私はStandardOpenOption.APPENDを使うことを考えました。しかし、私はそれがファイルの最後に追加されたくないので意味がないと感じました。既存のラインを置き換える必要があります。私は何かをもう一度見逃している? – AshwiniR

+0

私はちょうど追加を試みました。それはファイルの終わりにすべての内容(一致しなかった行を含む)を追加します。少なくともこれは、不一致の行が完全に失われていないことを私に伝えます。しかし、私は新しいコンテンツでファイルを書き換える方法を理解する必要があります。 – AshwiniR

答えて

16

は、ストリームから、フィルタに一致しないものを排除します。 (また、それは価値がある何のために、A)あなたは一度だけparallelを使用する必要があること、b)parallelは、c)それはあなたがするまでparallelを使用することがほとんどない良いアイデアません、I/Oのソースからのストリーム上でその効果的ではありません実際には非平行になっていて、遅すぎると感じました)

これは、replaceAllを実行しようとすると、パターンに一致する行を除外する必要はありません。あなたのコードは次のようになりますから、

try (Stream<String> lines = Files.lines(targetFile)) { 
    List<String> replaced = lines 
     .map(line-> line.replaceAll(plainTextPattern, replaceWith)) 
     .collect(Collectors.toList()); 
    Files.write(targetFile, replaced); 
} 
+0

すべてのコメントは非常に有益でした!皆さん、ありがとうございました! – AshwiniR

6

このファイルがどのように動作するかではないことを教えてくれてとても申し訳ありません。ファイルの途中に書き込む場合は、RandomAccessが必要です。 FilePointerを取得し、そのポインタを探し、そこから書き込みます。

あなたは、書き込みは、あなたが上書きしたいデータのサイズと同じであるデータのサイズたい場合に成立します。そうでない場合は、ファイルの末尾を一時バッファにコピーし、書き込むテキストに追加する必要があります。

btw、parallelStreamsIOにバインドしたタスクは、しばしば悪い考えです。 filterを使用して