简体   繁体   English

查找和替换文件中的单词/行

[英]Find and replace words/lines in a file

I have a file (more specifically, a log4j configuration file) and I want to be able to read in the file and pick out certain lines in the code and replace them.我有一个文件(更具体地说,是一个 log4j 配置文件),我希望能够读入该文件并挑选出代码中的某些行并替换它们。 For example, within the file there is a string of text that indicates the directory it is stored in, or the level of the logger.例如,在文件中有一个文本字符串,指示它存储的目录或记录器的级别。 I want to be able to replace those string of text without reading in the file, writing it to another file, and deleting the original file.我希望能够在不读取文件、将其写入另一个文件和删除原始文件的情况下替换这些文本字符串。 Is there a more efficient way of doing find and replace texts in a file using Java?有没有更有效的方法来使用 Java 查找和替换文件中的文本?

Here is an example of the text file I'm trying to work with:这是我正在尝试使用的文本文件的示例:

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

I want to be able to read the file and replace 'DEBUG' with another level or replace the file directory name 'C:/log.txt'.我希望能够读取文件并将“DEBUG”替换为另一个级别或替换文件目录名称“C:/log.txt”。 The log configuration file is also written in xml.日志配置文件也是用xml写的。 An example of that is featured below.下面是一个例子。

<?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>

I'm thinking it may be possible to use a hash map for this type of implementation?我在想可以对这种类型的实现使用哈希映射吗?

Any decent text editor has a search&replace facility that supports regular expressions.任何体面的文本编辑器都有支持正则表达式的搜索和替换功能。

If however, you have reason to reinvent the wheel in Java, you can do:但是,如果您有理由在 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));

This only works for Java 7 or newer.这仅适用于 Java 7 或更新版本。 If you are stuck on an older Java, you can do:如果您坚持使用较旧的 Java,则可以执行以下操作:

String content = IOUtils.toString(new FileInputStream(myfile), myencoding);
content = content.replaceAll(myPattern, myReplacement);
IOUtils.write(content, new FileOutputStream(myfile), myencoding);

In this case, you'll need to add error handling and close the streams after you are done with them.在这种情况下,您需要添加错误处理并在完成后关闭流。

IOUtils is documented at http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html IOUtils记录在http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html

After visiting this question and noting the initial concerns of the chosen solution, I figured I'd contribute this one for those not using Java 7 which uses FileUtils instead of IOUtils from Apache Commons.在访问了这个问题并注意到所选解决方案的最初关注点之后,我想我会为那些不使用 Java 7 的人贡献这个,Java 7 使用 FileUtils 而不是 Apache Commons 的 IOUtils。 The advantage here is that the readFileToString and the writeStringToFile handle the issue of closing the files for you automatically.这里的优点是readFileToStringwriteStringToFile会自动为您处理关闭文件的问题。 (writeStringToFile doesn't document it but you can read the source). (writeStringToFile 没有记录它,但您可以阅读源代码)。 Hopefully this recipe simplifies things for anyone new coming to this problem.希望这个食谱可以为任何新遇到这个问题的人简化事情。

  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();
}

above is my implementation of Meriton's example that works for me.以上是我对适用于我的 Meriton 示例的实现。 The fileName is the directory (ie. D:\\utilities\\settings.txt).文件名是目录(即 D:\\utilities\\settings.txt)。 I'm not sure what character set should be used, but I ran this code on a Windows XP machine just now and it did the trick without doing that temporary file creation and renaming stuff.我不确定应该使用什么字符集,但我刚才在 Windows XP 机器上运行了这段代码,它在不进行临时文件创建和重命名的情况下完成了这个技巧。

You might want to use Scanner to parse through and find the specific sections you want to modify.您可能希望使用 Scanner 来解析并找到要修改的特定部分。 There's also Split and StringTokenizer that may work, but at the level you're working at Scanner might be what's needed.也有 Split 和 StringTokenizer 可能有用,但在您在 Scanner 工作的级别上可能是需要的。

Here's some additional info on what the difference is between them: Scanner vs. StringTokenizer vs. String.Split以下是有关它们之间区别的一些附加信息: Scanner vs. StringTokenizer vs. String.Split

This is the sort of thing I'd normally use a scripting language for.这是我通常使用脚本语言的那种事情。 It's very useful to have the ability to perform these sorts of transformations very simply using something like Ruby/Perl/Python (insert your favorite scripting language here).能够使用 Ruby/Perl/Python 之类的工具非常简单地执行这些类型的转换非常有用(在此处插入您最喜欢的脚本语言)。

I wouldn't normally use Java for this since it's too heavyweight in terms of development cycle/typing etc.我通常不会为此使用 Java,因为它在开发周期/打字等方面太重量级了。

Note that if you want to be particular in manipulating XML, it's advisable to read the file as XML and manipulate it as such (the above scripting languages have very useful and simple APIs for doing this sort of work).请注意,如果您想特别处理 XML,建议将文件作为 XML 读取并按原样操作(上述脚本语言具有非常有用且简单的 API 来完成此类工作)。 A simple text search/replace can invalidate your file in terms of character encoding etc. As always, it depends on the complexity of your search/replace requirements.简单的文本搜索/替换可能会使您的文件在字符编码等方面无效。与往常一样,这取决于您的搜索/替换要求的复杂性。

You can use Java's Scanner class to parse words of a file and process them in your application, and then use a BufferedWriter or FileWriter to write back to the file, applying the changes.您可以使用 Java 的Scanner类来解析文件的单词并在您的应用程序中处理它们,然后使用BufferedWriterFileWriter写回文件,应用更改。

I think there is a more efficient way of getting the iterator's position of the scanner at some point, in order to better implement editting.我认为有一种更有效的方法可以在某个时候获取扫描仪的迭代器位置,以便更好地实现编辑。 But since files are either open for reading, or writing, I'm not sure regarding that.但是由于文件可以打开以供读取或写入,因此我不确定。

In any case, you can use libraries already available for parsing of XML files, which have all of this implemented already and will allow you to do what you want easily.在任何情况下,您都可以使用已经可用的库来解析 XML 文件,这些库已经实现了所有这些,并且可以让您轻松地做您想做的事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM