Java读取文件最后n行

代码由来

项目里需要读取最新的日志,可是最新的日志都在文件的最后几行,所以有了这个需求。
百度之后先研究了别人的代码,感觉一是逻辑不太好理解且注释比较少,二是代码偏向于演示,会有bug,没有办法拿来就用。所以自己写了这个方法,希望可以给需要的同学带来帮助。
这个方法实现的功能和Linux系统的tail命令是相同的。

实现过程

对这个方法我前前后后投入了很大精力,每改变一次实现方式,前面的工作都仿佛白做了一样。从读取功能基本实现,到解决读取空行和文档行数不足导致的bug。再到费尽心机的简化代码,到最后一次实现方式的改变直接解决之前所有问题。到考虑性能把缓存工具的更换和代码执行逻辑的优化。
这个过程让我意识到:再简单的需求,用上复杂的实现就算把人累死也得不到好的结果。作为一名程序员,拿到需求我们往往急于写代码,当看到杂乱的实现代码,我们又抓耳挠腮无从下手去改进。每当这个时候,我们一定要回头去看看我们的需求,想想有没有其他更简洁的实现方法,而不要困死在已有的代码里。

感谢 @万物皆字节 同学的建议。

如果这篇博客帮助到了你,你可给它点个赞,这将是对我莫大的鼓励,谢谢!

代码

    /**
     * 读取文件最后几行 <br>
     * 相当于Linux系统中的tail命令 读取大小限制是2GB
     *
     * @param filename 文件名
     * @param charset  文件编码格式,传null默认使用defaultCharset
     * @param rows     读取行数
     * @throws IOException IOException
     */
    public static String readLastRows(String filename, Charset charset, int rows) throws IOException {
        charset = charset == null ? Charset.defaultCharset() : charset;
        byte[] lineSeparator = System.getProperty("line.separator").getBytes();
        try (RandomAccessFile rf = new RandomAccessFile(filename, "r")) {
            // 每次读取的字节数要和系统换行符大小一致
            byte[] c = new byte[lineSeparator.length];
            // 在获取到指定行数和读完文档之前,从文档末尾向前移动指针,遍历文档每一个字节
            for (long pointer = rf.length(), lineSeparatorNum = 0; pointer >= 0 && lineSeparatorNum < rows;) {
                // 移动指针
                rf.seek(pointer--);
                // 读取数据
                int readLength = rf.read(c);
                if (readLength != -1 && Arrays.equals(lineSeparator,c)) {
                    lineSeparatorNum++;
                }
                //扫描完依然没有找到足够的行数,将指针归0
                if (pointer == -1 && lineSeparatorNum < rows) {
                    rf.seek(0);
                }
            }
            byte[] tempbytes = new byte[(int) (rf.length() - rf.getFilePointer())];
            rf.readFully(tempbytes);
            return new String(tempbytes, charset);
        }
    }
  • 8
    点赞
  • 6
    收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 5

打赏作者

益达哥哥

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值