我有一个文件(更具体地说,是一个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>
我在想这种类型的实现可能会使用哈希映射吗?
答案 0 :(得分:121)
任何体面的文本编辑器都有一个支持正则表达式的搜索和替换工具。
但是,如果你有理由在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
答案 1 :(得分:18)
在访问了这个问题并注意到所选解决方案的初始问题后,我想我会为那些不使用Java 7而不是来自Apache Commons的IOUtils的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);
}
答案 2 :(得分:3)
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();
}
以上是我对Meriton的例子的实现,对我有用。 fileName是目录(即D:\ utilities \ settings.txt)。我不确定应该使用什么字符集,但是我刚刚在Windows XP机器上运行了这个代码,它没有做临时文件创建和重命名的东西。
答案 3 :(得分:1)
您可能希望使用扫描程序进行解析并找到要修改的特定部分。还有Split和StringTokenizer可能有效,但是你在Scanner工作的水平可能就是需要的。
以下是关于它们之间区别的一些额外信息: Scanner vs. StringTokenizer vs. String.Split
答案 4 :(得分:1)
这是我通常使用脚本语言的东西。能够非常简单地使用像Ruby / Perl / Python这样的东西(在这里插入你喜欢的脚本语言)来执行这些变换非常有用。
我通常不会使用Java,因为它在开发周期/打字等方面过于沉重。
请注意,如果您希望特别操作XML,建议将文件作为XML读取并对其进行操作(上述脚本语言具有非常有用且简单的API来执行此类工作)。简单的文本搜索/替换可能会使您的文件在字符编码等方面失效。一如既往,它取决于您的搜索/替换要求的复杂性。
答案 5 :(得分:0)
您可以使用Java的Scanner
类来解析文件中的单词并在应用程序中处理它们,然后使用BufferedWriter
或FileWriter
写回文件,应用变化。
我认为有一种更有效的方法可以在某个时刻获取迭代器的扫描器位置,以便更好地实现编辑。但由于文件是开放阅读或写作,我不确定。
在任何情况下,您都可以使用已经可用于解析XML文件的库,这些库已经实现了所有这些,并且可以让您轻松地执行您想要的操作。