You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:12:57