我正在做一个任务,在这个任务中,我必须读取一个巨大的文件(大小约为1.5 GB,约有1600万条记录)。我面前有2个选择。
在原始测试中,用选项1读取记录数需要2900毫秒,用选项2需要1450毫秒。
测试程序如下。
选项1:
public static void reviewBufferedReader () {
long lineNumber = 0;
String line = null;
try (BufferedReader b = Files.newBufferedReader(Paths.get("D:\\\\Temp Data Files\\Data1.txt"), StandardCharsets.UTF_8)) {
executor = RecordsDistributionExecutor.getInstance();
while ((line = b.readLine()) != null) {
lineNumber++;
}
} catch (Exception e) {
System.err.println("Error in reviewBufferedReader : "+e.getMessage());
} finally {
}
System.out.println("Total no. of lines: "+lineNumber);
}
选项2:
public static void reviewFileChannelWithMappedByteBuffer () {
long lineNumber = 0;
try (RandomAccessFile raFile = new RandomAccessFile("D:\\\\Temp Data Files\\Data2.txt", "r");
FileChannel inChannel = raFile.getChannel();){
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
buffer.load();
char c;
for(int i = 0; i< buffer.limit(); i++) {
c = (char) buffer.get();
if ('\n' == c) {
lineNumber++;
}
}
buffer.clear(); // do something with the data and clear/compact it.
} catch (Exception e) {
System.err.println("Error in reviewFileChannelWithMappedByteBuffer : "+e.getMessage());
} finally {
}
System.out.println("Total no. of lines: "+lineNumber);
}
正如我所说,方案2的基本测试时间较少。
我有一个问题,在方案2中是否可以像方案1那样逐行读取文件数据。
谢谢。
Atul
在user207421的评论后,我改变了我的答案。我建议使用BufferedReader和更大的默认缓冲区大小没有帮助。
try(var reader = new BufferedReader(new FileReader(file), 128 * 1024)) { ... }
如果内存不是问题,Files.readAllBytes在我的PC上是最快的,可以计算0.5GB测试文件的行数,从NAS或SSD读取。
int lines = 0;
for (var b : Files.readAllBytes(f))
if (b == '\n') lines++;
FileInputStream也不遑多让,而且内存消耗较少。
int len = 0, lines = 0;
byte[] buffer = new byte[128 * 1024];
try(var in = new FileInputStream(f)) {
while (( len = in.read(buffer)) >= 0) {
for (int x = len - 1 ; x >= 0 ; x--) {
if (buffer[x] == '\n') lines++;
}
}
}