当前位置: 首页 > 面试题库 >

Java快速阅读文本文件的最后一行?

秦俊发
2023-03-14
问题内容

从Java中的[非常大]文件中读取文本的最后一行的最快,最有效的方法是什么?


问题答案:

以下是两个函数,一个函数返回文件的最后一个非空白行而不加载或单步浏览整个文件,另一个函数返回文件的最后N行而不单步浏览整个文件:

尾部的作用是直接缩放到文件的最后一个字符,然后逐个字符向后退一步,记录所看到的内容,直到找到换行符为止。找到换行符后,便会跳出循环。反转记录的内容,并将其放入字符串中并返回。0xA是新行,0xD是回车。

如果你的行尾是\r\ncrlf或其他“双换行符样式换行符”,那么你将必须指定n * 2行才能获得最后n行,因为每行计数2行。

public String tail( File file ) {
    RandomAccessFile fileHandler = null;
    try {
        fileHandler = new RandomAccessFile( file, "r" );
        long fileLength = fileHandler.length() - 1;
        StringBuilder sb = new StringBuilder();

        for(long filePointer = fileLength; filePointer != -1; filePointer--){
            fileHandler.seek( filePointer );
            int readByte = fileHandler.readByte();

            if( readByte == 0xA ) {
                if( filePointer == fileLength ) {
                    continue;
                }
                break;

            } else if( readByte == 0xD ) {
                if( filePointer == fileLength - 1 ) {
                    continue;
                }
                break;
            }

            sb.append( ( char ) readByte );
        }

        String lastLine = sb.reverse().toString();
        return lastLine;
    } catch( java.io.FileNotFoundException e ) {
        e.printStackTrace();
        return null;
    } catch( java.io.IOException e ) {
        e.printStackTrace();
        return null;
    } finally {
        if (fileHandler != null )
            try {
                fileHandler.close();
            } catch (IOException e) {
                /* ignore */
            }
    }
}

但是你可能不想要最后一行,而想要最后N行,因此请改用以下代码:

public String tail2( File file, int lines) {
    java.io.RandomAccessFile fileHandler = null;
    try {
        fileHandler = 
            new java.io.RandomAccessFile( file, "r" );
        long fileLength = fileHandler.length() - 1;
        StringBuilder sb = new StringBuilder();
        int line = 0;

        for(long filePointer = fileLength; filePointer != -1; filePointer--){
            fileHandler.seek( filePointer );
            int readByte = fileHandler.readByte();

             if( readByte == 0xA ) {
                if (filePointer < fileLength) {
                    line = line + 1;
                }
            } else if( readByte == 0xD ) {
                if (filePointer < fileLength-1) {
                    line = line + 1;
                }
            }
            if (line >= lines) {
                break;
            }
            sb.append( ( char ) readByte );
        }

        String lastLine = sb.reverse().toString();
        return lastLine;
    } catch( java.io.FileNotFoundException e ) {
        e.printStackTrace();
        return null;
    } catch( java.io.IOException e ) {
        e.printStackTrace();
        return null;
    }
    finally {
        if (fileHandler != null )
            try {
                fileHandler.close();
            } catch (IOException e) {
            }
    }
}

像这样调用以上方法:

File file = new File("D:\\stuff\\huge.log");
System.out.println(tail(file));
System.out.println(tail2(file, 10));


 类似资料:
  • 目前我正在使用扫描器/文件读取器,并使用while HasNextLine。我认为这种方法效率不高。有没有其他方法读取文件与此类似的功能?

  • 测试数据 # linecache_data.py import os import tempfile lorem = '''Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus eget elit. In posuere mi non risus. Mauris id quam posuere lectus soll

  • 问题内容: 目前,我正在使用扫描仪/文件阅读器,同时使用hasnextline。我认为这种方法效率不高。还有其他方法可以读取与此功能类似的文件吗? 问题答案: 您会发现这是所需的速度:您可以每秒读取数百万行。字符串拆分和处理很可能导致遇到的任何性能问题。

  • 问题内容: 我正在制作一个日志,我想读取log.txt文件的最后一行,但是在读取最后一行时,我无法使BufferedReader停止。 这是我的代码: 问题答案: 这是一个很好的解决方案。 在代码中,您可以仅创建一个名为的辅助变量,并不断将其初始化为当前行,如下所示:

  • 我想获得收件箱中任何邮件中包含的每个人的列表。现在我可以使用javax邮件API通过IMAP连接并下载消息: 线路信息【i】。getFrom()比我希望的要慢,因为is导致消息被延迟加载。我能做些什么来加快速度吗?E、 g.是否有某种批量加载方式可以代替逐个加载消息?这会加载整个消息吗?我是否可以只加载“收件人/发件人/抄送”字段或标题?POP会比IMAP快吗?

  • 问题内容: 我正在尝试读取“ file.txt”,然后使用Golang将内容放入变量中。这是我尝试过的… 文件已成功读取,并且从 os.Open 返回的返回类型为 * os.File 问题答案: 这取决于您要执行的操作。 它输出&{0xc082016240}的原因是因为您正在打印文件描述符()的指针值,而不是文件内容。要获取文件内容,可以从文件描述符中获取。 要将所有文件内容(以字节为单位)读取到