如何加快从海量文件(Java)读入的速度
基本上,对于我正在处理的这个任务,我们必须从一个大约一百万行的大文件中读取,将键和值存储在我们选择的数据结构中(我使用哈希表),提供更改键值的功能,然后将键值存储保存回一个文件中。我正在使用布谷鸟散列法以及我在哈佛大学的一篇论文中发现的一种叫做“隐藏”的方法来完成这项工作,我对所有这些都很满意。我唯一关心的是程序从文件中读取数据所花费的时间 文件的格式是,每行都有一个键(整数)和一个值(字符串),如下所示: 12345“abcdef” 23456“bcdefg” 等等。我想出的阅读方法如下:如何加快从海量文件(Java)读入的速度,java,performance,data-structures,file-io,Java,Performance,Data Structures,File Io,基本上,对于我正在处理的这个任务,我们必须从一个大约一百万行的大文件中读取,将键和值存储在我们选择的数据结构中(我使用哈希表),提供更改键值的功能,然后将键值存储保存回一个文件中。我正在使用布谷鸟散列法以及我在哈佛大学的一篇论文中发现的一种叫做“隐藏”的方法来完成这项工作,我对所有这些都很满意。我唯一关心的是程序从文件中读取数据所花费的时间 文件的格式是,每行都有一个键(整数)和一个值(字符串),如下所示: 12345“abcdef” 23456“bcdefg” 等等。我想出的阅读方法如下: p
private static void readData() throws IOException {
try {
BufferedReader inStream = new BufferedReader(new FileReader("input/data.db"));
StreamTokenizer st = new StreamTokenizer(inStream);
String line = inStream.readLine();
do{
String[] arr = line.split(" ");
line = inStream.readLine();
Long n = Long.parseLong(arr[0]);
String s = arr[1];
//HashNode<Long, String> node = HashNode.create(n, s);
//table = HashTable.empty();
//table.add(n, s);
}while(line != null);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void readData()引发IOException{
试一试{
BufferedReader inStream=新的BufferedReader(新的文件读取器(“input/data.db”);
StreamTokenizer st=新的StreamTokenizer(流内);
字符串行=inStream.readLine();
做{
字符串[]arr=line.split(“”);
line=inStream.readLine();
Long n=Long.parseLong(arr[0]);
字符串s=arr[1];
//HashNode node=HashNode.create(n,s);
//table=HashTable.empty();
//表.添加(n,s);
}while(line!=null);
}catch(filenotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
该方法在实际获取数据方面效果很好,但是我用一百万行的测试文件对其进行了测试,它花了大约20分钟的时间才全部读取完。当然,现在读取文件中的数据不是一个很快的时间,我肯定有更好的方法
我尝试了几种不同的输入方法(BufferedInputStream和FileInputStream,使用Scanner,但是文件扩展名是.db,所以Scanner无法工作,我最初没有标记器,但添加了它,希望它能有所帮助)。我不知道我运行它的计算机是否有很大的不同。我有一台MacBook Air,目前正在运行;不过,我会让一位同事在他的笔记本电脑上运行一下,看看这是否会有帮助。任何关于如何帮助这一点的意见,或者我可能会做些什么来减缓如此多的事情,都将非常真诚和感谢
另外,请不要因为我在Mac上编程而讨厌我:-)摆脱
流标记器。使用BufferedReader.readLine()
,您每秒可以读取数百万行,这就是您真正要做的:没有标记化
但我强烈怀疑时间不是花在I/O上,而是花在处理每一行上
注意:您的do/while
循环通常写为while
循环:
while ((line = in.readLine()) != null)
这种方式更加清晰,并且没有NPE的风险。您可以使用“java.nio.file.*”,以下代码是用java 8风格编写的,但如果需要,可以轻松修改为java上的早期版本:
Map<Long, String> map = new HashMap<>();
Files.lines(Paths.get("full-path-to-your-file")).forEach(line -> {
String[] arr = line.split(" ");
Long number = Long.parseLong(arr[0]);
String string = arr[1];
map.put(number, string);
});
Map Map=newhashmap();
Files.line(path.get(“文件的完整路径”)).forEach(line->{
字符串[]arr=line.split(“”);
Long number=Long.parseLong(arr[0]);
字符串字符串=arr[1];
map.put(数字、字符串);
});
由于并行执行Files.lines(…).forEach(…)
,因此还有额外的性能提升。这意味着这些行将不符合顺序(在我们的例子中,您不需要它),如果您需要它符合顺序,您可以调用:forEachOrdered()
在我的MacBook上,将200万条这样的记录写入一个文件,然后读取并填充地图不到5秒钟。我一直在等待代码完全计算,最后没有错误。我还故意忽略了第一行,第一行是一个包含文件名的头,我不想让它读入。不幸的是,这是除了Main方法之外的整个主类,Main方法只是调用这个方法,到目前为止就是这样。我将移除标记器,看看这是否有任何帮助。这对我来说太棒了。我调整了程序的其余部分,完成了散列函数,现在读取和存储100万行大约需要2秒钟。非常感谢。