当我们在读取文件的时候,通常都是从前向后读取,那如果要读取文件的最后一行内容,要如何操作呢?
顺序遍历读取,直到文件最后一行
public static String readLastLineV0(File file) {
String lastLine = "";
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
String currentLine = "";
while ((currentLine = bufferedReader.readLine()) != null) {
lastLine = currentLine;
}
} catch (Exception e) {
log.error("file read error, msg:{}", e.getMessage(), e);
}
return lastLine;
}
该方式很简单,从前向后读取即可,直到最后一行。
利用RandomAccessFile指定位置,从后向前读取
public static String readLastLineV1(File file) {
// 存储结果
StringBuilder builder = new StringBuilder();
try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
// 指针位置开始为0,所以最大长度为 length-1
long fileLastPointer = randomAccessFile.length() - 1;
// 从后向前读取文件
for (long filePointer = fileLastPointer; filePointer != -1; filePointer--) {
// 移动指针指向
randomAccessFile.seek(filePointer);
int readByte = randomAccessFile.readByte();
if (0xA == readByte) {
// LF='\n'=0x0A 换行
if (filePointer == fileLastPointer) {
// 如果是最后的换行,过滤掉
continue;
}
break;
}
if (0xD == readByte) {
// CR ='\r'=0x0D 回车
if (filePointer == fileLastPointer - 1) {
// 如果是倒数的回车也过滤掉
continue;
}
break;
}
builder.append((char) readByte);
}
} catch (Exception e) {
log.error("file read error, msg:{}", e.getMessage(), e);
}
return builder.reverse().toString();
}
该方式主要是利用RandomAccessFile可以seek到指定位置读取的方式。从文件的最后向前读取,当遇到0xA(换行)或者0xD(回车)时,利用StringBuilder缓存一下读取到的数据,最后将数据reverse即是最后一行数据。
利用commons-io中的ReversedLinesFileReader
maven导入依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
public static String readLastLineV2(File file) {
String lastLine = "";
try (ReversedLinesFileReader reversedLinesReader = new ReversedLinesFileReader(file, Charset.defaultCharset())) {
lastLine = reversedLinesReader.readLine();
} catch (Exception e) {
log.error("file read error, msg:{}", e.getMessage(), e);
}
return lastLine;
}
该方式可以直接读取到最后一行数据。有兴趣的同学可以自行看一下源码,非常少。它的实现是思路是先将文件拆成多个FilePart。读取位置定位是基于SeekableByteChannel的position方法。而FilePart的readLine实现中,可以一次读取多个bytes。
总结
以上三种读取文件最后一行的方法中,推荐使用commons-io中的ReversedLinesFileReader,使用方式也比较简单。
网友评论