添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

项目里需要读取最新的日志,可是最新的日志都在文件的最后几行,所以有了这个需求。
百度之后先研究了别人的代码,感觉一是逻辑不太好理解且注释比较少,二是代码偏向于演示,会有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 ) ; Java读取文件最后几行项目里需要读取最新的日志,可是最新的日志都在文件的最后几行,所以有了这个需求。百度之后先研究了别人的代码,感觉一是逻辑不太好理解,二是代码偏向于测试,没有办法哪来就用。所以自己写了这个方法,希望可以给看到的同学带来帮助。也算我自己的一点积累吧。 /** * 读取文件最后几行 * @param filename * @param rows * @thr... 1、首先在pom 文件 导入依赖 <!--在 Java 中,我们可以使用 Apache Commons IO 的 ReversedLinesFileReader 类 读取文件 最后 。 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId>
最近线上有一个需求,下载系统日志,但是由于tomcat 日志比较大,超过 几百兆甚至几个G。如果用传统方法,将日志 文件 读取 到内存,显然是有问题的。 下面提供一种 截取日志 最后 N 而不会导致内存溢出的方法。使用commons.io 包的ReversedLinesFileReader对象。 代码如下: package ygw.study.play; import org.apache.commons.io.FileUtils; import org.apache.commons.io.input.R.
当我们在 读取文件 的时候,通常都是从前向后 读取 ,那如果要 读取文件 最后 内容,要如何操作呢? 顺序遍历 读取 ,直到 文件 最后 public static String readLastLineV0(File file) { String lastLine = ""; try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { String currentLine = ""; java 动态获取 文件 内容的前几 ,就是当 文件 读取 到该 文件 的某 内容时,动态获取该 内容的前几 ,这里由于业务需要动态获取当7 ,和后7 代码如下: 这里采用 RandomAccessFile 一 读取文件 。 new Thread(new Runnable() { @Override public void run() { try { public static void main(String[] args) { //调用 读取 方法,定义 文件 以及 读取 数 List list = readLastNLine(new File("D:/1.txt"), 5L); if (list != null
import java .io.FileNotFoundException; import java .io.IOException; import java .io.RandomAccessFile; public class ReverseRead { 在你的基础上做了点修改 [code=java] public static String readLastRows(String filePath, int rows) throws IOException { Charset charset = Charset.defaultCharset(); try (RandomAccessFile rf = new RandomAccessFile(filePath, "r")) { // 每次读取的字节数要和系统换行符大小一致 byte[] c = new byte[1]; // 在获取到指定行数和读完文档之前,从文档末尾向前移动指针,遍历文档每一个字节 for (long pointer = rf.length(), lineSeparatorNum = 0; pointer >= 0 && lineSeparatorNum < rows;) { // 移动指针 rf.seek(pointer--); // 读取数据 int readLength = rf.read(c); if (readLength != -1 && c[0] == 10) { 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); [/code]