如何用OpenCSV逐行读取含损坏行的CSV并避免批量跳过?
问题描述
我需要读取一个存在损坏行的CSV文件,示例如下:
"name","address","link" "7eleven","city, street, 1",https://somelink/1 //正常行 Baby-Gym,"city, street, 2\",https://somelink/2 //损坏行,因address字段含\",序列
示例中第二条数据行损坏,原因是address字段包含\",序列。我无法修改原CSV文件,仅想读取并忽略这些损坏行,但使用com.opencsv库的csvReader.readNext()方法时,单条损坏行导致意外跳过约5000行。
当前使用的CSV读取代码:
try (Reader reader = new BufferedReader(new InputStreamReader(is))) { CSVParser parser = new CSVParserBuilder() .withSeparator(',') .withQuoteChar('"') .build(); try (CSVReader csvReader= new CSVReaderBuilder(reader) .withSkipLines(1) .withCSVParser(parser) .build()) { Set<info> infoList = new HashSet<>(); String[] infoParts; while ((infoParts = csvReader.readNext()) != null) { // 处理逻辑 } } }
尝试过使用new CSVReaderBuilder(reader).withMultilineLimit(1),但仅抛出异常;查阅CSVParser和CSVReader文档也未找到合适配置。请问如何用OpenCSV逐行读取CSV,避免因单条损坏行而跳过大量行?
解决方案
核心思路是强制逐行解析,避免OpenCSV因未闭合的引号跨多行读取,以下是两种可行方案:
方案一:逐行读取后单独解析
用BufferedReader逐行读取文本,再用CSVParser单独解析每行,遇到解析错误直接跳过该行,不影响后续行处理。
修改后的代码:
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) { // 跳过表头行 br.readLine(); CSVParser parser = new CSVParserBuilder() .withSeparator(',') .withQuoteChar('"') .withStrictQuotes(true) // 开启严格引号模式,解析错误时抛出异常 .build(); Set<info> infoList = new HashSet<>(); String line; while ((line = br.readLine()) != null) { try { String[] infoParts = parser.parseLine(line); // 处理正常行逻辑 infoList.add(new info(infoParts[0], infoParts[1], infoParts[2])); } catch (CSVException e) { // 捕获解析异常,跳过损坏行 System.out.println("跳过损坏行: " + line); continue; } } } catch (IOException e) { e.printStackTrace(); }
这种方式完全控制每行解析流程,损坏行仅被单独跳过,不会牵连其他行。
方案二:配置CSVReader错误处理策略
通过设置多行限制并捕获异常,手动推进到下一行,适合坚持使用CSVReader的场景:
try (Reader reader = new BufferedReader(new InputStreamReader(is))) { CSVParser parser = new CSVParserBuilder() .withSeparator(',') .withQuoteChar('"') .build(); try (CSVReader csvReader= new CSVReaderBuilder(reader) .withSkipLines(1) .withCSVParser(parser) .withMultilineLimit(1) // 限制每行仅解析当前行,禁止跨多行读取 .build()) { Set<info> infoList = new HashSet<>(); while (true) { try { String[] infoParts = csvReader.readNext(); if (infoParts == null) break; // 处理正常行逻辑 infoList.add(new info(infoParts[0], infoParts[1], infoParts[2])); } catch (CSVException e) { // 手动跳过损坏行,需确保reader为BufferedReader类型 ((BufferedReader)reader).readLine(); System.out.println("跳过损坏行"); } } } } catch (IOException e) { e.printStackTrace(); }
关键说明
损坏行的核心问题是未闭合的引号,OpenCSV默认会持续读取直到找到闭合引号,导致跨多行。强制逐行解析可从根源避免该问题;解析异常CSVException会在引号不匹配、字段数量不符时抛出,捕获后跳过该行即可。
内容的提问来源于stack exchange,提问作者Anna L
相关产品推荐
相关产品推荐

