この特定の問題を解決するために正規表現を使用することはありません。ファイル全体をメモリにロードし、処理し、再書き込みする必要があります。それは本質的に悪いことではありませんが、十分な大きさのファイルがある場合は、ストリーム ベースのソリューションの方がおそらく優れています。
あなたがすることは、入力ファイルを一度に 1 行ずつ処理し、次のブール値を維持することです。
true
目的のルールの宣言ヘッダーに一致する行を見つけると、 になります。
- で、一致する行を見つけると に
false
なります。true
end
ブール値が に設定されている間に発生したすべての行を破棄しtrue
、他のすべての行を一時出力ファイル (たとえば、で作成) に書き込みますFile#createTempFile
。
各行で、ブール値がtrue
の場合は無視します。それ以外の場合は、一時出力ファイルに書き込みます。
プロセスの最後に、 を使用して入力ファイルを一時出力ファイルで上書きしますFile#renameTo
。
このソリューションには、アトミックであるという追加の利点があることに注意してください。処理中にエラーが発生した場合でも、入力ファイルが部分的に書き込まれるリスクはありません。完全に上書きされるか、まったく上書きされないため、予期しないIOException
s から保護されます。
次のコードは、それを実装する方法を示しています。これは必ずしも完全な実装ではありませんが、定型コードの途中で失われたアルゴリズムを説明する必要があります。
public void deleteFrom(String id, File file) throws IOException {
BufferedReader reader;
String line;
boolean inRule;
File temp;
PrintWriter writer;
reader = null;
writer = null;
try {
// Streams initialisation.
temp = File.createTempFile("delete", "rule");
writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temp), "utf-8")));
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
inRule = false;
// For each line in the file...
while((line = reader.readLine()) != null) {
// If we're parsing the rule to delete, we're only interested in knowing when we're done.
if(inRule) {
if(line.trim().equals("end"))
inRule = false;
}
// Otherwise, look for the beginning of the targetted rule.
else if(line.trim().equals("rule \"" + id + "\""))
inRule = true;
// Normal line, we want to keep it.
else
writer.println(line);
}
}
// Stream cleanup.
finally {
if(reader != null)
reader.close();
if(writer != null)
writer.close();
}
// We're done, copy the new file over the old one.
temp.renameTo(file);
}