【问题标题】:Regex to search and replace text in a large file正则表达式搜索和替换大文件中的文本
【发布时间】:2015-05-31 05:34:16
【问题描述】:

我正在一个大文件中搜索多行模式,如果发现需要替换内容。我想以一种内存有效的方式来实现这一点。我当前的实现以 4096 字节的形式从文件中读取文本。然后它应用正则表达式搜索替换并将结果保存在缓冲区输出流中。通过不将整个文件加载到内存中,这确实给了我一些内存改进,但是我使用 map/flush 调用进行了很多 IO。需要有关进一步改进我的代码的建议。此外,如果要搜索的模式被分成相邻的块,算法也会失败。关于如何有效地搜索替换分割成相邻块的文本的任何想法。假设:要搜索的文本总是小于 4096 字节。

public void searchAndReplace (String inputFilePath, String outputFilePath) {

    Pattern HEADER_PATTERN =  Pattern.compile("<a [^>]*>[^(</a>)]*</a>", Pattern.DOTALL);
    Charset UTF8 = Charset.forName("UTF-8");
    File outputFile = new File(outputfilepath);
    if (!outputFile.exists()) {
        outputFile.createNewFile();
    }

    FileInputStream inputStream = new FileInputStream(new File(inputfilepath));
    FileOutputStream outputStream = new FileOutputStream(outputFile);

    FileChannel inputChannel = inputStream.getChannel();

    final long length = inputChannel.size();
    long pos = 0;
    while (pos < length) {
        int remaining = (int)(length - pos) > 4096 ? 4096 : (int)(length - pos);
        MappedByteBuffer map = inputChannel.map(FileChannel.MapMode.READ_ONLY, pos, remaining);
        CharBuffer cbuf = UTF8.newDecoder().decode(map);
        Matcher matcher = HEADER_PATTERN.matcher(cbuf);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "Some text");
        }
        matcher.appendTail(sb);
        outputStream.write(sb.toString().getBytes());
        outputStream.flush();
        pos = pos + 4096;
    }

    inputStream.close();
    outputStream.close(); 
}

【问题讨论】:

  • 一定要用java吗?如果没有,您使用什么操作系统?
  • 你更喜欢使用 java,因为我希望应用程序独立于操作系统。如果没有其他替代方案,希望使用 OS grep/find。
  • 很确定你的正则表达式没有做你认为的那样:它要求锚不包含任何字符(, &lt;, /, a, &gt; or )。我想你实际上想要"&lt;a [^&gt;]*&gt;.*?&lt;/a&gt;"
  • 也许您应该使用流式 XML 解析器来处理这个问题。
  • +Duncan :是的,我最终也做了同样的事情。谢谢

标签: java regex io nio text-search


【解决方案1】:

声明一个不太可能出现在您的字符串中的特殊字符列表。然后测试您的字符串以确保其中一个特殊字符不会退出其中。在您想要执行正则表达式的区域之间植入特殊字符。然后您可以使用 /[^¬]*myRegExHere[^\¬]/g

进行查找/替换或搜索

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 2013-06-14
    • 2011-08-11
    相关资源
    最近更新 更多