如何在java中快速将大型csv文件转换为json数组

时间:2014-06-19 11:59:48

标签: java json

我想将像20000到50000记录文件这样的大型csv文件转换为json数组,但转换需要将近1分钟,有没有办法在不到5秒的时间内实现它。

  ResourceBundle rb = ResourceBundle.getBundle("settings");
        String path = rb.getString("fileandfolder.Path");
        System.out.println(path + "ssdd");
        String csvPath = request.getParameter("DP") != null ? request
                .getParameter("DP").toString() : "";

        String orname = path + csvPath;
        File file = new File(orname);

        FileReader fin = new FileReader(file); //Read file one by one
        BufferedReader bi = new BufferedReader(fin);

        int res;
        String csv = "";

        while ((res = fin.read()) != -1) {
            csv = csv + ((char) res); //Converted int to char and stored in csv

        }
        long start3 = System.nanoTime();
        JSONArray array = CDL.toJSONArray(csv);
        String Csvs = array.toString();

        long time3 = System.nanoTime() - start3;
        System.out
                .printf("Took %.3f seconds to convert to a %d MB file, rate: %.1f MB/s%n",
                        time3 / 1e9, file.length() >> 20, file.length()
                                * 1000.0 / time3);

3 个答案:

答案 0 :(得分:1)

尝试

StringBuilder sb = new StringBuilder();
while ((res = fin.read()) != -1) {
    sb.append((char) res); //Converted int to char and stored in csv
}
String csv = sb.toString();

使用+连接字符串很慢,你应该使用StringBuilder或StringBuffer

答案 1 :(得分:1)

您的代码中存在两个明显的性能问题,这两个问题都在此代码段中:

    while ((res = fin.read()) != -1) {
        csv = csv + ((char) res);
    }

第一个问题:fin是一个无缓冲的FileReader,因此每个read()调用实际上都在进行系统调用。每个系统调用都有数百甚至数千条指令。而且您正在为输入文件中的每个字符执行此操作。

补救措施:从bi而不是fin读取。 (这就是你为...创造的......大概是。)

第二个问题:每次执行csv = csv + ((char) res);时,您都会创建一个比前一个字符长一个字符的新字符串。如果输入文件中包含N个字符,则最终会复制大约N^2个字符以构建字符串。

补救措施:不要连接字符串,而是使用StringBuilder ......就像这样:

    StringBuilder sb = new StringBuilder();
    ....
        sb.append((char) res);
    ....
    String csv = sb.toString();

此时,我不清楚将csv字符串转换为JSON时是否存在性能问题;即在这个片段中。

    JSONArray array = CDL.toJSONArray(csv);
    String Csvs = array.toString();

很遗憾,我们不知道您实际使用的是JSONArrayCDL个类。因此,很难说为什么它们很慢,或者是否有更快的方式进行转换。 (但我怀疑,最大的性能问题出现在早期的片段中。)

答案 2 :(得分:-1)

这个csv = csv + ((char) res)非常慢,你一次只读一个字符,然后用旧字符串和新字符分配一个新字符串。

要将文件中的所有文本加载到字符串中,请执行以下操作:

static String readFile(String path, Charset encoding) 
  throws IOException 
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

(来自https://stackoverflow.com/a/326440/360211,请注意,如果使用java 7)

,会有更简洁的方法

像这样使用而不是循环:

String csv = readFile(orname, StandardCharsets.UTF_8);