从文本文件中读取大量数据的最快方法
Fastest way to read a large number from text file
所以我在文本文件中存储了一个非常大的数字(1500 万位),我正在使用这种方法读取数字
BufferedReader Br1 = null;
StringBuilder Final = new StringBuilder("");
System.out.println("Loading......");
Br1 = new BufferedReader (new FileReader("NumberFind.txt"));
String Line = Br1.readLine();
while(Line != null) {
Final.append(Line);
Line = Br1.readLine();
}
sum1 = new BigInteger(Final.toString());
Br1.close();
System.out.println("Loaded");
这可行,但加载整个数字大约需要 45 分钟,有没有更快的加载方法?
如果其中只有一个数字,您的文件只有 14.3 兆字节。我不知道 BufferedReader、BigInteger 等的什么怪癖导致了 45 分钟的加载,但它可能只是那个行读取循环。您应该能够在几秒钟内将整个文件读入内存,而不是几分钟。
尝试在没有 BufferedReader 的情况下将整个文件(或可能只是包含数字的部分)读入字符串。请参阅 FileReader.readAsBinaryString() 以完成此操作。
将数字作为字符串存储在内存中后,您应该能够像在上面的代码示例中所做的那样,通过将字符串参数传递给它来构造一个新的 BigInteger。
如果这不能解决所有问题,并且您想要更多见解,我建议缩小发生 45 分钟延迟的范围。我猜它在你的线阅读循环中,但我可能是错的。如果您在某些环境中,例如嵌入式设备,对 CPU、磁盘读取时间等有异常限制,这可能是一个因素。
可以创建初始容量为文件大小(可能减去行尾)的 StringBuilder。
使用 BigInteger 而不是 StringBuilder 来累积结果可以节省大量内存。我不知道那是否确实更快。
Path path = Paths.get("NumberFind.txt");
BigInteger n = Files.lines(path)
.reduce(// 1. the start value
BigDecimal.ZERO,
// 2. the accumulator adding the next line
(num, line) ->
num.scaleByPowerOfTen(line.length()).add(new BigDecimal(line)),
// 3. The combiner for a parallel stream (irrelevant)
(num1, num2) ->
num1.scaleByPowerOfTen(num2.toString().length()).add(num2))
.toBigInteger();
读取一行并将其转换为 BigDecimal。先前的行累积为一个 BigDecimal,然后必须乘以 10n,其中 n 是行长度。
我使用 BigDecimal,因为它有一个很好的 scaleByPowerOfTen
。最后,BigDecimal 被转换为 BigInteger。
这个解决方案可能会更慢。我很好奇。
所以我在文本文件中存储了一个非常大的数字(1500 万位),我正在使用这种方法读取数字
BufferedReader Br1 = null;
StringBuilder Final = new StringBuilder("");
System.out.println("Loading......");
Br1 = new BufferedReader (new FileReader("NumberFind.txt"));
String Line = Br1.readLine();
while(Line != null) {
Final.append(Line);
Line = Br1.readLine();
}
sum1 = new BigInteger(Final.toString());
Br1.close();
System.out.println("Loaded");
这可行,但加载整个数字大约需要 45 分钟,有没有更快的加载方法?
如果其中只有一个数字,您的文件只有 14.3 兆字节。我不知道 BufferedReader、BigInteger 等的什么怪癖导致了 45 分钟的加载,但它可能只是那个行读取循环。您应该能够在几秒钟内将整个文件读入内存,而不是几分钟。
尝试在没有 BufferedReader 的情况下将整个文件(或可能只是包含数字的部分)读入字符串。请参阅 FileReader.readAsBinaryString() 以完成此操作。
将数字作为字符串存储在内存中后,您应该能够像在上面的代码示例中所做的那样,通过将字符串参数传递给它来构造一个新的 BigInteger。
如果这不能解决所有问题,并且您想要更多见解,我建议缩小发生 45 分钟延迟的范围。我猜它在你的线阅读循环中,但我可能是错的。如果您在某些环境中,例如嵌入式设备,对 CPU、磁盘读取时间等有异常限制,这可能是一个因素。
可以创建初始容量为文件大小(可能减去行尾)的 StringBuilder。
使用 BigInteger 而不是 StringBuilder 来累积结果可以节省大量内存。我不知道那是否确实更快。
Path path = Paths.get("NumberFind.txt");
BigInteger n = Files.lines(path)
.reduce(// 1. the start value
BigDecimal.ZERO,
// 2. the accumulator adding the next line
(num, line) ->
num.scaleByPowerOfTen(line.length()).add(new BigDecimal(line)),
// 3. The combiner for a parallel stream (irrelevant)
(num1, num2) ->
num1.scaleByPowerOfTen(num2.toString().length()).add(num2))
.toBigInteger();
读取一行并将其转换为 BigDecimal。先前的行累积为一个 BigDecimal,然后必须乘以 10n,其中 n 是行长度。
我使用 BigDecimal,因为它有一个很好的 scaleByPowerOfTen
。最后,BigDecimal 被转换为 BigInteger。
这个解决方案可能会更慢。我很好奇。