场景:
大文本文件,普通的文本编辑器无法直接打开,我们只想知道文本最后的关键几行信息。
如果直接将文件全部读入内存显然不可取。
可利用RandomAccessFile完成,RandomAccessFile是随机读写类,是可以对文件本身的内容直接随机进行操作的,可以在文件的指定位置的读取和写入内容,这在很多时候都是很方便的。
package com.yx.filedemo;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
/**
* FileUtil
*
* @author yx
* @date 2019/12/19 22:00
*/
public class FileUtil {
public static void main(String[] args) {
File file = new File("D:\\FileUtil.java");
List<String> result1 = readLastLines(file, 10);
if (null != result1 && result1.size() > 0) {
for (int i = result1.size() - 1; i >= 0; i--) {
System.out.println(result1.get(i));
}
}
}
/**
* 读出文件的最后n行
*
* @param file 文件
* @param num 第几行
* @return 读取文本文件的最后n行
*/
public static List<String> readLastLines(File file, int num) {
if (num == 0) {
return null;
}
// 判断该文件是否存在,可读
if (!file.exists() || file.isDirectory() || !file.canRead()) {
return null;
}
List<String> result = new ArrayList<String>();
// 行数
int count = 0;
RandomAccessFile rafFile = null;
try {
// 选择只读模式
rafFile = new RandomAccessFile(file, "r");
// 读取文件长度
long length = rafFile.length();
// 判断长度
if (length == 0L) {
return null;
} else {
// 因为是倒数,所以从最大值开始读起
long pos = length - 1;
// 当下一个大于0,则代表文章有内容
while (pos > 0) {
// 开始读取
rafFile.seek(pos);
// 如果读取到\n代表是读取到一行
if (rafFile.readByte() == '\n') {
// 使用readLine获取当前行 ,转码,如果存在乱码可以转码
String line =
new String(rafFile.readLine().getBytes("ISO-8859-1"), "utf-8");
// 保存结果
result.add(line);
// 行数统计,如果到达了指定的行数,就跳出循环
count++;
if (count == num) {
break;
}
}
pos--;
}
//next为0,代表长度为1
if (pos == 0) {
rafFile.seek(0);
result.add(rafFile.readLine());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (rafFile != null) {
try {
rafFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}