Java 从大文件(超过700MB)中提取模式的更有效的方法是什么

Java 从大文件(超过700MB)中提取模式的更有效的方法是什么,java,performance,parsing,large-files,Java,Performance,Parsing,Large Files,我遇到一个问题,需要从本地计算机解析文本文件。有一些复杂情况: 文件可能相当大(700mb+) 该模式出现在多行中 我需要在模式之后存储行信息 我使用BufferReader、String.indexOf和String.substring(获取第3项)创建了一个简单的代码 文件中有一个名为code=的键(模式),它在不同的块中多次出现。程序使用BufferReader.readLine从该文件中读取每一行。它使用indexOf检查模式是否出现,然后在模式后提取文本并存储在公共字符串中 当我用60

我遇到一个问题,需要从本地计算机解析文本文件。有一些复杂情况:

  • 文件可能相当大(700mb+)
  • 该模式出现在多行中
  • 我需要在模式之后存储行信息
  • 我使用
    BufferReader
    String.indexOf
    String.substring
    (获取第3项)创建了一个简单的代码

    文件中有一个名为
    code=
    的键(模式),它在不同的块中多次出现。程序使用
    BufferReader.readLine
    从该文件中读取每一行。它使用
    indexOf
    检查模式是否出现,然后在模式后提取文本并存储在公共字符串中

    当我用600mb文件运行我的程序时,我注意到它处理文件时性能最差。我在CodeRanch上读到一篇文章说,
    Scanner
    类不适合大文件

    是否有一些技术或库可以提高我的性能

    提前谢谢

    以下是我的源代码:

    String codeC = "code=[";
    String source = "";
    try {
        FileInputStream f1 = new FileInputStream("c:\\Temp\\fo1.txt");
        DataInputStream in = new DataInputStream(f1);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
    
        String strLine;
        boolean bPrnt = false;
        int ln = 0;
        // Read File Line By Line
        while ((strLine = br.readLine()) != null) {
            // Print the content on the console
            if (strLine.indexOf(codeC) != -1) {
                ln++;
                System.out.println(strLine + " ---- register : " + ln);
                strLine = strLine.substring(codeC.length(), strLine.length());
                source = source + "\n" + strLine;
            }
        }
        System.out.println("");
        System.out.println("Lines :" + ln);
        f1.close();
    } catch ( ... ) {
        ...
    }
    
    看看

    来自甲骨文的一篇优秀的文章

    来自JAVADoc的复制粘贴:

    用于根据正则表达式指定的模式匹配字符序列的类

    模式类的一个实例表示一个正则表达式,该正则表达式以字符串形式指定,语法与Perl使用的语法类似

    Matcher类的实例用于根据给定模式匹配字符序列。输入通过CharSequence接口提供给匹配器,以支持对来自各种输入源的字符进行匹配

    除非另有说明,否则将null参数传递给此包中任何类或接口中的方法将导致引发NullPointerException


    您的这段代码非常可疑,可能至少是您性能问题的一部分原因:

    FileInputStream f1 = new FileInputStream("c:\\Temp\\fo1.txt");
    DataInputStream in = new DataInputStream(f1);
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
    
    您无缘无故地涉及到
    DataInputStream
    ,事实上,将其用作
    读取器的输入可以被视为代码中断的情况。写下以下内容:

    InputStream f1 = new FileInputStream("c:\\Temp\\fo1.txt");
    BufferedReader br = new BufferedReader(new InputStreamReader(fr));
    

    对性能的一个巨大损害是您正在使用的
    System.out
    ,尤其是在Eclipse中运行时测量性能,但即使是从命令行运行。我猜,这是造成瓶颈的主要原因。在您为最高性能而设定目标时,请确保您在主循环中不会打印任何内容。

    除了Marko回答的内容外,我建议关闭br,而不是f1:

    br.close()
    
    这不会影响性能,但更干净。(关闭最外面的流)

    它工作得非常好

    我遵循了OldCurmudgeonMarko TopolnikAlexWien的建议,我的表现提高了1000%。之前,程序花了2个小时来完成所描述的操作并在文件中写入响应。 现在它花了5分钟!!而SYSO仍保留在源代码中

    我认为巨大改进的原因是像OldCurmudgeon建议的那样,将字符串“source”更改为哈希集“source”。但是我删除了DataInputStream并使用了“br.close”


    谢谢大家

    我的意思是,他正在链中插入一个
    DataInputStream
    。这是不需要的。读者部分还可以。他是否应该更好地使用br.close()而不是f1.close()?使用
    br.close()
    ,这会更习惯,是的,但不会影响性能和系统资源(打开的文件)将以任何方式发布。除了下面@Marko所建议的内容之外,我建议您在StringBuilder中收集结果,或者最好是在列表中收集结果。将其构建为一个潜在的巨大字符串可能会极大地影响内存占用。我认为最大的改进是删除System.out.prinltn()。