【问题标题】:How to convert a big csv file into json array quickly in java如何在java中快速将一个大的csv文件转换为json数组
【发布时间】:2014-06-19 11:59:47
【问题描述】:

我想将 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);

【问题讨论】:

  • Cvs 库..???你能告诉我任何例子吗?
  • 我已将其从不再需要的代码中删除。
  • 然后更改您的代码以反映这一点,您的代码不会按原样编译。所以long time3 = System.nanoTime() - start2; 应该是long time3 = System.nanoTime() - start3;
  • 请注意,通过提供大量没有计时的不必要的文件读取代码(显然),您在这里混淆了很多人。
  • 一个网络响应中的 50k 个条目无论如何听起来都是个坏主意。

标签: java json


【解决方案1】:

您的代码中有两个明显的性能问题,这两个问题都在这个 sn-p 中:

    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是否也存在性能问题;即在这个sn-p中。

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

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

【讨论】:

  • 除非我们找出 start2 的初始化位置,否则这可能不是问题。
  • 是的......计时码也相当混乱。但我准备接受 OP 的代码确实需要 分钟 来处理一个大文件。性能问题是真实存在的。
【解决方案2】:

试试

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

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

【讨论】:

  • 他不是在计时读取数据,他只是在计时字符串到数组的转换
  • 那还是没用,他检查的时间是把String变成JSONArray的过程。
  • @mikea 在你也投反对票之前,请注意 OP 使用的是 start2,而不是 start3
  • @JonathanDrapeau 不正确,long start3 = System.nanoTime(); 不用于时间计算。
  • @JonathanDrapeau 除非他删除了一行,否则我知道它在循环之上,用于一次读取一个字符。
【解决方案3】:

这个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);

【讨论】:

  • 检查什么正在计时,这不是问题。
  • 根据另一个答案,他没有计时这部分代码
  • @mikea 根据另一个答案,他的时间来自start2 而不是start3
  • @JonathanDrapeau 我确实检查过。他的时间来自start2 而不是start3。这是一个很好的猜测,在复制的部分上方的一行中。
  • 无论谁认为这是“没用”,猜猜最后哪个代码在接受的答案上变慢了,那个循环。
猜你喜欢
  • 2020-06-08
  • 1970-01-01
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
相关资源
最近更新 更多