ファイル(具体的にはlog4j構成ファイル)があり、そのファイルを読み取ってコード内の特定の行を選択し、それらを置換できるようにしたいのです。たとえば、ファイル内には、保存先のディレクトリまたはロガーのレベルを示すテキスト文字列があります。ファイルを読み取ったり、別のファイルに書き込んだり、元のファイルを削除したりせずに、これらのテキスト文字列を置き換えることができるようにしたいと思います。 Javaを使用してファイル内のテキストを検索および置換するより効率的な方法はありますか?
これが、私が使用しようとしているテキストファイルの例です。
log4j.rootLogger=DEBUG, A0
log4j.appender.A0=org.Apache.log4j.RollingFileAppender
log4j.appender.A0.File=C:/log.txt
log4j.appender.A0.MaxFileSize=100KB
log4j.appender.A0.MaxBackupIndex=1
log4j.appender.A0.layout=org.Apache.log4j.RollingFileAppender
log4j.appender.A0.layout.ConversionPattern=%-4r [%t] %-5p: %c %x - %m%n
ファイルを読み取って、「DEBUG」を別のレベルに置き換えるか、ファイルのディレクトリ名「C:/log.txt」を置き換えることができます。ログ構成ファイルもxmlで記述されています。その例を以下に示します。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<appender class="org.Apache.log4j.RollingFileAppender" name="A0">
<param name="append" value="false"/>
<param name="File" value="C:/log/.txt"/>
<param name="MaxBackupIndex" value="1"/>
<param name="MaxFileSize" value="100KB"/>
<layout class="org.Apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-4r [%t] %-5p: %c %x - %m%n"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="A0"/>
</root>
</log4j:configuration>
このタイプの実装にハッシュマップを使用することは可能だと思いますか?
適切なテキストエディタには、正規表現をサポートする検索と置換機能があります。
ただし、Javaで車輪を再発明する理由がある場合は、次のことができます。
Path path = Paths.get("test.txt");
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("foo", "bar");
Files.write(path, content.getBytes(charset));
これはJava 7以降でのみ機能します。古いJavaで動けなくなった場合は、次のことができます。
String content = IOUtils.toString(new FileInputStream(myfile), myencoding);
content = content.replaceAll(myPattern, myReplacement);
IOUtils.write(content, new FileOutputStream(myfile), myencoding);
この場合、エラー処理を追加し、処理が完了したらストリームを閉じる必要があります。
IOUtils
は http://commons.Apache.org/proper/commons-io/javadocs/api-release/org/Apache/commons/io/IOUtils.html で文書化されています
この質問にアクセスし、選択したソリューションの最初の懸念に気付いた後、Apache CommonsのIOUtilsの代わりにFileUtilsを使用するJava 7 readFileToString および writeStringToFile は、ファイルを自動的に閉じる問題を処理します(writeStringToFileはドキュメント化されていませんが、ソースを読み取ることができます)。この問題に新たに加わった人のために物事を簡素化します。
try {
String content = FileUtils.readFileToString(new File("InputFile"), "UTF-8");
content = content.replaceAll("toReplace", "replacementString");
File tempFile = new File("OutputFile");
FileUtils.writeStringToFile(tempFile, content, "UTF-8");
} catch (IOException e) {
//Simple exception handling, replace with what's necessary for your use case!
throw new RuntimeException("Generating file failed", e);
}
public static void replaceFileString(String old, String new) throws IOException {
String fileName = Settings.getValue("fileDirectory");
FileInputStream fis = new FileInputStream(fileName);
String content = IOUtils.toString(fis, Charset.defaultCharset());
content = content.replaceAll(old, new);
FileOutputStream fos = new FileOutputStream(fileName);
IOUtils.write(content, new FileOutputStream(fileName), Charset.defaultCharset());
fis.close();
fos.close();
}
上記は、メリトンの例の実装です。 fileNameはディレクトリです(例:D:\ utilities\settings.txt)。どの文字セットを使用すべきかわかりませんが、このコードをWindows XPマシンで実行したところ、一時ファイルの作成や名前の変更を行わずにトリックを実行しました。
Scannerを使用して解析し、変更する特定のセクションを見つけることができます。動作する可能性のあるSplitおよびStringTokenizerもありますが、スキャナーで作業しているレベルで必要な場合があります。
以下に、それらの違いについての追加情報を示します。 Scanner vs. StringTokenizer vs. String.Split
これは、私が通常スクリプト言語を使用するようなものです。 Ruby/Perl/Pythonのようなものを使用して、これらの種類の変換を非常に簡単に実行できると非常に便利です(ここにお気に入りのスクリプト言語を挿入します)。
開発サイクル/タイピングなどの点であまりにも重いので、通常はJavaを使用しません。
XMLの操作に特化したい場合は、ファイルをXMLとして読み取り、そのように操作することをお勧めします(上記のスクリプト言語には、この種の作業を行うための非常に便利でシンプルなAPIがあります)。単純なテキスト検索/置換は、文字エンコードなどの点でファイルを無効にする可能性があります。いつものように、検索/置換要件の複雑さに依存します。
JavaのScanner
クラスを使用してファイルの単語を解析し、アプリケーションで処理した後、BufferedWriter
またはFileWriter
を使用してファイルに書き戻し、変更。
編集をより適切に実装するために、ある時点でイテレーターのスキャナーの位置を取得するより効率的な方法があると思います。しかし、ファイルは読み取り用または書き込み用に開いているため、それについてはわかりません。
いずれの場合でも、XMLファイルの解析にすでに利用可能なライブラリを使用できます。これらのライブラリはすべて既に実装されており、必要なことを簡単に実行できます。