我想将像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);
答案 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();
很遗憾,我们不知道您实际使用的是JSONArray
和CDL
个类。因此,很难说为什么它们很慢,或者是否有更快的方式进行转换。 (但我怀疑,最大的性能问题出现在早期的片段中。)
答案 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);