如何为csv文件创建主索引

时间:2014-03-08 06:29:27

标签: java csv

我有一个50,000,000行csv文件。

name,  salary, text
anna,  100,   good
mary,  50,    low
amber, 60,    ok
   ...........

我需要添加主索引p_index

p_index,  name,  salary, text
1,        anna,  100,   good
2,        mary,  50,    low
3,        amber, 60,    ok
       ...........

到目前为止,我逐行使用BufferedReader读取。然后使用PrintWriter从原始csv复制到新的csv。然而,这种方法很慢。 。大约20分钟。有没有办法更快地添加自动增量值。这是我的代码

public class Test {
    static PrintWriter pw;

    public static void main(String[] args) {
        FileReader fr = new FileReader("test.csv");
        File file = new File("test2.csv");
        BufferedReader reader = new BufferedReader(fr);

        String line = reader.readLine();
        pw = new PrintWriter(file);
        pw.println("P_INDEX," + line);

        int i = 0;
        while ((line = reader.readLine()) != null) {
            pw.println(i + "," + line);
            i++;
        }

        pw.close();
        System.exit(0);
    }

}

任何人都可以对我的代码进行更正以提高其工作速度吗?

由于

2 个答案:

答案 0 :(得分:2)

一些可能性。

  1. 对任何更改进行基准测试,针对最佳缓冲区大小进行有条理的“二进制搜索”等。使用较小的文件,在几十秒内处理。

  2. 不要使用String,只使用原始字节数组。文件的8位字符编码和Java字符串的16位unicode之间的转换是像这样的批量数据情况下的性能杀手(但是在文件的开头注意UTF-8 BOM,如果有一个插入后的第一个字节它)。

  3. 如果您有定期格式化的固定列CSV文件,则最小行长度。扫描下一行的缓冲区时,可以跳过这么多字节。

  4. 使用java.nio

  5. 优化缓冲区大小(参见上面的第1项)。

  6. 使用2个线程处理前一个时读取下一个缓冲区。也许把写入第三个线程(在这种情况下,扫描可能与性能无关,没有点跳过部分行)。

答案 1 :(得分:0)

默认情况下,PrintWriter具有相当小的缓冲区。您可能会提高性能,确保使用带有更大缓冲区的BufferedWriter创建PrintWriter。例如:

new PrintWriter(new BufferedWriter(new FileWriter(file), 1000000));

如果您已经了解了数据集的大小,您还可以为读取器和写入器设置缓冲区大小,以减少对磁盘的读/写次数。

使用~4Gb的示例文件,您的示例代码编写耗时约53秒。使用带有BufferedWriter的相同输入文件并使用10Mb缓冲区写入需要大约48秒