如何加速从大量文件中读取(Java)

时间:2017-10-13 23:13:27

标签: java performance data-structures file-io

所以基本上,对于我正在进行的这项任务,我们必须从大约一百万行的大文件中读入,将键和值存储在我们选择的数据结构中(I' m使用哈希表),提供更改键值的功能,然后将键值存储保存回文件中。我使用杜鹃散列方法以及我从哈佛大学的一篇论文中发现的一种方法,称为" stashing"要做到这一点,我对所有这一切都很好。我唯一关心的是程序只是从文件中读取数据所花费的时间。

对文件进行格式化,使每行都有一个键(整数)和一个如下所示的值(String):

12345' abcdef'

23456' bcdefg'

等等。我想出来的方法就是这样:

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();
    }

}

该方法适用于实际获取数据,但是我使用我们的一百万行测试文件对其进行了测试,它花了大约20分钟才能完全读完所有内容。当然,这不是&#39 ;从文件中读取数据的快速时间,我很肯定必须有更好的方法。

我已经尝试了几种不同的输入方法(带有FileInputStream的BufferedInputStream,使用Scanner但是文件扩展名是.db,所以Scanner没有工作,我最初没有使用tokenizer但是希望它添加它有助于)。我不知道我运行它的计算机是否有很大的不同。我有一台MacBook Air,我目前正在运行;但是,我有一个配偶在他的笔记本电脑上运行它,看看是否可能有助于它。任何关于如何帮助这个或我可能做什么来减缓这些事情的意见都会得到真诚和非常感激。

P.S。请不要讨厌我在Mac上编程:-)

2 个答案:

答案 0 :(得分:2)

您可以使用&#34; java.nio.file。*&#34;,以下代码是用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);
        });

Files.lines(..).forEach(...)并行执行以来,还有额外的性能提升。这意味着这些行不会按顺序排列(在我们的例子中 - 你不需要它),万一你需要它可以调用:forEachOrdered()

在我的MacBook上,花了不到5秒的时间将200万条此类记录写入文件,然后读取并填充地图。

答案 1 :(得分:1)

摆脱StreamTokenizer。您可以使用BufferedReader.readLine()每秒读取数百万行,这就是您所做的一切:没有标记化。

但我强烈怀疑时间不是花在I / O上,而是处理每一行。

注意您的do/while循环通常写为while循环:

while ((line = in.readLine()) != null)

这种方式更加清晰,没有NPE的风险。

相关问题