#java #csv #opencsv
#java #csv #opencsv
Вопрос:
У меня есть следующие две реализации чтения csv-файлов, рассматриваемые CSV-файлы не такие большие (5 мегабайт).
Первая реализация использует OpenCSV, вторая использует StringTokenizer.
Первая привела к ошибке нехватки памяти, даже когда я увеличил максимальную память кучи java до 1G (Xmx), хотя реализация StringTokenizer ненадежна, но у меня нет выбора, поскольку мне нужно прочитать csv-файл в память.
Я не понимаю, почему версия OpenCSV потребляет так много памяти, учитывая небольшой размер csv-файла (в нем 200 тысяч строк, но размер файла всего около 5 метров). что делает OpenCSV Reader, для чего требуется так много памяти? Версия StringTokenizer быстро проходит через нее.
вот ошибка, вызванная реализацией OpenCSV:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.Arrays.copyOfRange(Arrays.java:3209)
at java.lang.String.<init>(String.java:215)
at java.lang.StringBuilder.toString(StringBuilder.java:430)
at au.com.bytecode.opencsv.CSVParser.parseLine(Unknown Source)
at au.com.bytecode.opencsv.CSVParser.parseLineMulti(Unknown Source)
at au.com.bytecode.opencsv.CSVReader.readNext(Unknown Source)
private List<String[]> parseCSV(File f) {
List<String[]>res=new Vector<String[]>();
CSVReader reader=null;
try{
reader = new CSVReader(new BufferedReader(new FileReader(f)));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
for(int i=0;i<nextLine.length;i )if(nextLine[i]!=null)nextLine[i]=nextLine[i].trim();
res.add(nextLine);
}
}catch(IOException exp){
exp.printStackTrace();
}finally{
if(reader!=null)try {
reader.close();
} catch (IOException ex) {
Logger.getLogger(DataStream2.class.getName()).log(Level.SEVERE, null, ex);
}
}
return res;
}
private List<String[]> parseCSV(File f) {
List<String[]>res=new Vector<String[]>();
BufferedReader br=null;
try{
br = new BufferedReader(new FileReader(f));
String line =null;
while((line=br.readLine())!=null){
StringTokenizer st=new StringTokenizer(",");
String[]cur=new String[st.countTokens()];
for(int i=0;i<cur.length;i ){
cur[i]=st.nextToken().trim();
}
res.add(cur);
}
}catch(IOException exp){
exp.printStackTrace();
}
finally{
if(br!=null)try {
br.close();
} catch (IOException ex) {
Logger.getLogger(DataStream2.class.getName()).log(Level.SEVERE, null, ex);
}
}
return res;
}
Ответ №1:
Возможно, это маловероятно, но я бы предположил, что ваши входные данные могут вызывать ошибку в библиотеке opencsv, возможно, заставляя ее застревать в цикле.
Загрузка для opencsv предоставляет исходный код и библиотеки, поэтому вы должны быть в состоянии отладить код самостоятельно.
Поскольку stacktrace не показывает номера строк для кода opencsv, я бы предположил, что вам нужно будет изменить целевой javac в скрипте сборки, чтобы включить «debug = true», чтобы включить отладочную компиляцию кода.
Ответ №2:
оказывается, что в версии StringTokenizer есть ошибка, поэтому в обеих версиях не хватает памяти.
Ответ №3:
Apache Solr использует commons-csv, поэтому я бы рекомендовал попробовать. Solr, использующий его, является большим одобрением.