【问题标题】:Optimal way to find if a string is present in a file查找文件中是否存在字符串的最佳方法
【发布时间】:2017-10-06 00:11:18
【问题描述】:

我有一个包含数千行的文本文件。查找文件中是否存在某个字符串的最佳方法是什么?

要么将整个文件读入一个字符串,然后使用string.contains 方法,要么使用Files.readAllLines 方法创建所有行的列表,然后循环遍历列表中的每一行并检查该行是否包含所需的字符串与否?

更新:我使用的是 Java 7。搜索限制为每个文件(10 个文件)搜索 1-2 个字符串。要搜索的字符串随文件而变化。如果找到字符串,我想停止搜索。

【问题讨论】:

  • 查找子字符串搜索算法,如Rabin-KarpAho-Cosarick
  • 在不知道这种情况多久会发生的情况下很难回答您的问题。即它是一次性搜索吗?搜索是否会经常发生,但查找的输入字符串经常发生变化?搜索是否会经常发生但输入文件经常更改?
  • 您的具体要求是什么?在任何一行中找到字符串的时刻,您要停止吗?还是要打印所有出现的事件?

标签: java string file


【解决方案1】:

将行保留在列表中几乎没有什么好处。不过,您提出的两种方法都存在同样的警告。

如果您只关心文件中的特定行,您可能不想在内存中保留不需要的行。如果您使用的是 Java 8,则可以使用 Files.lines() 通过流逐行读取文件。否则,guava 的LineProcessor,也可以这样做。

此示例使用流来查找与字符串匹配的所有行并将它们返回到列表中。

List<String> lines = Files.lines(path)
            // findFirst() can be used get get the first match and stop.
            .filter(line -> line.contains("foo"))
            .collect(Collectors.toList());

这个是用番石榴做的。

import com.google.common.io.Files;
import com.google.common.io.LineProcessor;

List<String> lines = Files.readLines(file, new LineProcessor<List<String>>() {

    private List<String> lines = new ArrayList<>();

    @Override
    public boolean processLine(String line) throws IOException {
        if (line.contains("foo"))
            lines.add(line);
        return true; // return false to stop
    }

    @Override
    public List<String> getResult() {
        return lines;
    }

});

【讨论】:

    【解决方案2】:

    考虑到您使用的是 Java 8 并且文件很大,最好使用Streams API。可能有两种情况:一种是当您找到包含stringToSearch 的行时要返回,或者您想探索所有行以查找stringToSearch。示例代码如下:

    String fileName = "c://SomeFile.txt";
    String stringToSearch = "dummy";
    try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
         // Find first
         Optional<String> lineHavingTarget = stream.filter(l -> l.contains(stringToSearch)).findFirst();
         // search all
         stream.filter(l -> l.contains(stringToSearch)).forEach(System.out::println);
         // do whatever
        } catch (IOException e) {
             // log exception
        }
    

    所以读取文件的所有行似乎是个坏主意。最好逐行阅读。如果您有兴趣了解最快的字符串搜索算法,请查看this 链接。

    【讨论】:

      【解决方案3】:

      由于文件包含很多行,因此最好逐行读取该文件,而不是将其所有内容都放入程序内存中。所以基本上,阅读一行检查你的字符串是否存在并继续前进。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        • 2016-01-02
        相关资源
        最近更新 更多