Java 慢速CSV行解析和拆分
我正在尝试解析一个超过100000行的csv,性能问题甚至不允许我在点击“Exception in thread”main“java.lang.OutOfMemoryError:超出GC开销限制”之前到达文件的末尾 有什么不对劲吗,或者我有什么可以改进的地方吗Java 慢速CSV行解析和拆分,java,performance,csv,Java,Performance,Csv,我正在尝试解析一个超过100000行的csv,性能问题甚至不允许我在点击“Exception in thread”main“java.lang.OutOfMemoryError:超出GC开销限制”之前到达文件的末尾 有什么不对劲吗,或者我有什么可以改进的地方吗 public static List<String[]> readCSV(String filePath) throws IOException{ List<String[]> csvLine= new A
public static List<String[]> readCSV(String filePath) throws IOException{
List<String[]> csvLine= new ArrayList<String[]>();
CSVReader reader = new CSVReader(new FileReader(filePath), '\n');
String[] row;
while((row = reader.readNext()) != null){
csvLine.add(removeWhiteSpace(row[0].toString().split(",")));
}
reader.close();
return csvLine;
}
private static String[] removeWhiteSpace(String[] split) {
for(int index =0; index < split.length;index++){
split[index] = split[index].trim();
}
return split;
}
公共静态列表readCSV(字符串文件路径)引发IOException{
List csvLine=new ArrayList();
CSVReader reader=新的CSVReader(新的文件读取器(文件路径),'\n');
字符串[]行;
while((row=reader.readNext())!=null){
添加(删除空格(行[0].toString().split(“,”));
}
reader.close();
返回csvLine;
}
私有静态字符串[]删除空白(字符串[]拆分){
对于(int index=0;index
将如此大的文件放入内存是一个设计错误。
根据您想做什么,您应该编写一个新的已处理文件,或者将这些行放入dba。
这实现了第一个:
FileInputStream inputStream = null;
Scanner sc = null;
try {
inputStream = new FileInputStream(path);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
String line = sc.nextLine();
// System.out.println(line);
}
// note that Scanner suppresses exceptions
if (sc.ioException() != null) {
throw sc.ioException();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (sc != null) {
sc.close();
}
}
首先,您的内存不足,因为所有行都被添加到列表中 其次,您使用的是String.split(),速度非常慢 第三,不要试图通过编写自己的解析代码来处理CSV,因为这种格式有很多边缘情况(需要处理分隔符、引号等的转义) 解决方案是为此使用库,例如。您应该能够在不到一秒钟的时间内读取一百万行 要进行分析,只需执行以下操作:
public static IterableResult<String[], ParsingContext> readCSV(String filePath) {
File file = new File(filePath);
//configure the parser here. By default all values are trimmed
CsvParserSettings parserSettings = new CsvParserSettings();
//create the parser
CsvParser parser = new CsvParser(parserSettings);
//create an iterable over rows. This will not load everything into memory.
IterableResult<String[], ParsingContext> rows = parser.iterate(file);
return rows;
}
public static void main(String... args) throws IOException {
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setProcessor(new AbstractRowProcessor() {
@Override
public void rowProcessed(String[] row, ParsingContext context) {
//modify the row data here.
}
});
CsvWriterSettings writerSettings = new CsvWriterSettings();
CsvRoutines routines = new CsvRoutines(parserSettings, writerSettings);
FileReader input = new FileReader("c:/path/to/input.csv");
FileWriter output = new FileWriter("c:/path/to/output.csv");
routines.parseAndWrite(input, output);
}
希望这有帮助
免责声明:我是这个图书馆的作者。它是开源和免费的(Apache 2.0许可)。您正试图将整个100000行数据集加载到内存中。将堆大小增加到大于数据集预期大小的值,或更改程序,使其不会一次加载所有数据。不要将整个csv文件存储在程序中。你为什么要读csv?您打算如何处理正在读取的数据?在读取文件时创建对象并计算统计数据,然后擦除对象并继续执行此操作,直到到达csv的末尾。您正在执行哪些统计,以及如何将csv数据转换为对象?是的,问题是您的算法错误。您似乎不需要将所有数据加载到内存中,请重写代码,使其一次处理一行。您可以通过将
for
和while
循环组合起来,将内存需求减半:dividedList.add(删除空格(行[0]。拆分(“,”)代码>这说明了如何实现编写一个新文件?嘿,如果你有时间,我想问一个简单的问题(使用非常好的库),我正在尝试解析CSV1的一行,将其与CSV2的每一行进行比较,然后移动到CSV1的下一行并重复。您是否认为这比使用数据填充对象并执行相同操作的成本更低?CSV1将有100万行。最需要做的是使用-Xms8G-Xmx8G
运行应用程序,并将两个文件作为列表加载到内存中。然后在内存中对两个列表进行排序,并按顺序运行比较。如果您的数据太大,无法放入内存,您可能可以使用数据库来存储数据。如果没有出路,就采用基于文件的方法。
public static void main(String... args) {
//this is your output file
File output = new File("c:/path/to/output.csv");
//configure the writer if you need to
CsvWriterSettings settings = new CsvWriterSettings();
//create the writer. Here we write to a file
CsvWriter writer = new CsvWriter(output, settings);
//get the row iterator
IterableResult<String[], ParsingContext> rows = readCSV("c:/temp");
try {
//do whatever you need to the rows here
for (String[] row : rows) {
//then write it each one to the output.
writer.writeRow(row);
}
} finally {
//cleanup
rows.getContext().stop();
writer.close();
}
}
public static void main(String... args) throws IOException {
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setProcessor(new AbstractRowProcessor() {
@Override
public void rowProcessed(String[] row, ParsingContext context) {
//modify the row data here.
}
});
CsvWriterSettings writerSettings = new CsvWriterSettings();
CsvRoutines routines = new CsvRoutines(parserSettings, writerSettings);
FileReader input = new FileReader("c:/path/to/input.csv");
FileWriter output = new FileWriter("c:/path/to/output.csv");
routines.parseAndWrite(input, output);
}