如何在java中将一个大的csv文件快速转换成json数组

如何在java中将一个大的csv文件快速转换成json数组,java,json,Java,Json,我想将一个大的csv文件(如20000到50000个记录文件)转换为json数组,但转换需要将近1分钟,有没有办法在5秒内完成 ResourceBundle rb = ResourceBundle.getBundle("settings"); String path = rb.getString("fileandfolder.Path"); System.out.println(path + "ssdd"); String csvPath =

我想将一个大的csv文件(如20000到50000个记录文件)转换为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);
试一试

使用+连接字符串速度较慢,应使用StringBuilfer或StringBuffer。此
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);
}
(请注意,如果使用java 7,有一种更干净的方法)

像这样使用,而不是循环:

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

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

    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时是否存在性能问题;i、 在这个片段中

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

不幸的是,我们不知道您实际使用的
JSONArray
CDL
类是什么。因此,很难说它们为什么慢,或者是否有更快的转换方法。(但我怀疑,最大的性能问题在前面的代码片段中。)

Cvs库。。???你能给我看一下它的例子吗?我已经从代码中删除了它,不再需要它了。然后改变你的代码以反映这一点,你的代码不会按原样编译。所以
longtime3=System.nanoTime()-start2可能应该是
longtime3=System.nanoTime()-start3请注意,通过提供大量不必要的文件读取代码(显然没有计时),您已经把这里的很多人弄糊涂了。一个网络响应中的50k条目听起来是个坏主意。他没有计时读取数据,他只是计时字符串到数组的转换,这仍然没有帮助,他检查的时间是将
String
放入
JSONArray
@mikea的过程,在你也投票否决我之前,注意OP使用
start2
来计时,而不是
start3
@JonathanDrapeau不正确,
long start3=System.nanoTime()
不用于时间计算。@JonathanDrapeau除非他删除了一行,否则我知道它位于每次读取文件一个字符的循环上方。检查正在计时的内容,这不是问题所在。根据另一个答案,他没有计时文件的这一部分code@mikea根据另一个答案,,他是从
start2
开始计时的,而不是
start3
@JonathanDrapeau,我查过了。他从
start2
开始计时,而不是
start3
。这是一个很好的猜测,就在复制的部分上方的一行。无论谁否决了这一点,认为“没有用”,猜猜在接受的答案,即循环中,什么代码最终会变慢。除非我们找到
start2
的初始化位置,否则这可能不是问题。是的。。。计时代码也相当混乱。但是我准备接受OP的代码确实需要几分钟来处理一个大文件。性能问题是真实存在的。
    JSONArray array = CDL.toJSONArray(csv);
    String Csvs = array.toString();