Java 使用圆周率的 10 亿位
Java use 1 billion digits of pi
我正在尝试编写一个程序来搜索 pi 的前 10 亿位数字并找到用户指定的数字,我面临的问题是如何使用 pi...我有一个 .txt 文件包含 pi(我也将它分解为 96 个不同的文件,因为 java 无法处理这么大的文件)所有数字都在第一行....
代码(仅使用96个文件读取和保存pi):
for(int i = 1;i <= 96; i++){
String filename = "";
if(i <= 9){
filename = "res//t//output2_00000" + i + "(500001).txt";
}else{
filename = "res//t//output2_0000" + i + "(500001).txt";
}
Scanner inFile = new Scanner(new FileReader(filename));
ar.add(inFile.nextLine());
}
List<String> pi = new ArrayList<String>();
for(int i = 0; i<97;i++){
System.out.println(i);
for(String j : ar.get(i).split("")){
pi.add(j);
}
}
这似乎工作正常,直到崩溃并出现以下错误(最后的打印语句是 3):
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.String.substring(Unknown Source)
at java.lang.String.subSequence(Unknown Source)
at java.util.regex.Pattern.split(Unknown Source)
at java.lang.String.split(Unknown Source)
at java.lang.String.split(Unknown Source)
at main.Main.main(Main.java:29)
有没有办法克服它,有没有办法让它运行得更快?
提前致谢。
如果您尝试将超过 1GB 的数据加载到堆中,您可能会用完堆内存。只需检查每个文件的搜索字符串,然后关闭文件。
不要拆分文本文件:这是错误的解决方案,找到一个跨文件拆分的数字会很痛苦。 当然 Java 可以处理大文件:您认为用 Java 编写的数据库还能如何工作?!
考虑使用 Apache Commons IO,它为您提供 LineIterator
:
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"/*probably*/);
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
LineIterator.closeQuietly(it);
}
您不需要将整个文件加载到内存中。使用 RandomAccessFile,您可以打开一个文件,将光标放在您想要的位置并从中读取:
RandomAccessFile raf = new RandomAccessFile(
new File("/home/adenoyelle/dev/pi.txt"), "r");
raf.seek(1_000_000);
System.out.println(raf.read());
注意:raf.read()
returns一个字节的数据。您可能需要根据需要重新解释它。
示例:
for(int i = 0; i< 10; i++) {
raf.seek(i);
System.out.println((char)raf.read());
}
输出:
3
.
1
4
1
5
9
2
6
5
注意 2 :如 SaviourSelf 所述,如果您需要一次读取多个字节,请选择 read(byte [] b)
.
我正在尝试编写一个程序来搜索 pi 的前 10 亿位数字并找到用户指定的数字,我面临的问题是如何使用 pi...我有一个 .txt 文件包含 pi(我也将它分解为 96 个不同的文件,因为 java 无法处理这么大的文件)所有数字都在第一行.... 代码(仅使用96个文件读取和保存pi):
for(int i = 1;i <= 96; i++){
String filename = "";
if(i <= 9){
filename = "res//t//output2_00000" + i + "(500001).txt";
}else{
filename = "res//t//output2_0000" + i + "(500001).txt";
}
Scanner inFile = new Scanner(new FileReader(filename));
ar.add(inFile.nextLine());
}
List<String> pi = new ArrayList<String>();
for(int i = 0; i<97;i++){
System.out.println(i);
for(String j : ar.get(i).split("")){
pi.add(j);
}
}
这似乎工作正常,直到崩溃并出现以下错误(最后的打印语句是 3):
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.String.substring(Unknown Source)
at java.lang.String.subSequence(Unknown Source)
at java.util.regex.Pattern.split(Unknown Source)
at java.lang.String.split(Unknown Source)
at java.lang.String.split(Unknown Source)
at main.Main.main(Main.java:29)
有没有办法克服它,有没有办法让它运行得更快? 提前致谢。
如果您尝试将超过 1GB 的数据加载到堆中,您可能会用完堆内存。只需检查每个文件的搜索字符串,然后关闭文件。
不要拆分文本文件:这是错误的解决方案,找到一个跨文件拆分的数字会很痛苦。 当然 Java 可以处理大文件:您认为用 Java 编写的数据库还能如何工作?!
考虑使用 Apache Commons IO,它为您提供 LineIterator
:
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"/*probably*/);
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
LineIterator.closeQuietly(it);
}
您不需要将整个文件加载到内存中。使用 RandomAccessFile,您可以打开一个文件,将光标放在您想要的位置并从中读取:
RandomAccessFile raf = new RandomAccessFile(
new File("/home/adenoyelle/dev/pi.txt"), "r");
raf.seek(1_000_000);
System.out.println(raf.read());
注意:raf.read()
returns一个字节的数据。您可能需要根据需要重新解释它。
示例:
for(int i = 0; i< 10; i++) {
raf.seek(i);
System.out.println((char)raf.read());
}
输出:
3
.
1
4
1
5
9
2
6
5
注意 2 :如 SaviourSelf 所述,如果您需要一次读取多个字节,请选择 read(byte [] b)
.