如何使用Java的Apache Commons CSV库移除CSV文件重复列
用Apache Commons CSV实现CSV重复列移除的方案
首先明确核心前提:
Apache Commons CSV的核心定位是CSV格式的解析与输出,常被用来做重复行去重,但没有内置的"重复列自动移除/跳过"的开箱即用能力。碰到带重复表头的CSV文件时,默认配置下甚至会因为规则限制直接抛出解析异常。要实现重复列的跳过,只需要结合库的原生API做少量自定义逻辑适配即可,实现成本很低。
核心实现逻辑
重复列的判定完全基于表头匹配:遍历解析出的所有原始表头,仅保留每个表头第一次出现的位置,后续同名列对应的列全部跳过。
这个逻辑和你现有代码的规则是完全兼容的:比如你开了忽略表头大小写、自动trim表头前后空格的配置,重复列的判定会自动套用这些规则,不需要额外调整。
步骤拆解
- 调整解析配置,允许重复表头存在
默认配置下,Commons CSV 检测到重复表头名会直接抛出IllegalArgumentException,必须手动开启重复表头允许,才能拿到完整的原始表头列表。 - 基于原始表头计算需要保留的列索引
逐一遍历所有解析到的表头,记录已出现过的表头名称,碰到第一次出现的列就把索引加入保留列表,碰到重复的列就直接标记跳过。 - 逐行读取数据时,仅按照保留的索引取值
不要直接用record.get("列名")的方式取值——存在重复列时,这个方法只会返回最后一个同名列的字段值,完全没法控制保留哪一个重复列,基于索引取值是最可靠的方式。
适配你现有代码的完整实现
// 用try-with-resources自动关闭资源,避免IO泄漏 try ( Reader reader = Files.newBufferedReader(Paths.get("user.csv")); CSVParser parser = CSVFormat.DEFAULT .withFirstRecordAsHeader() .withIgnoreHeaderCase() .withTrim() // 关键配置:允许重复表头存在,否则解析会直接报错 .withAllowDuplicateHeaderNames() .parse(reader); ) { // 获取全部原始表头,计算需要保留的列索引 Set<String> existingHeaders = new HashSet<>(); List<Integer> keepColumnIndex = new ArrayList<>(); List<String> rawHeaderList = parser.getHeaderNames(); for (int i = 0; i < rawHeaderList.size(); i++) { String currentHeader = rawHeaderList.get(i); // 仅保留第一次出现的列 if (!existingHeaders.contains(currentHeader)) { existingHeaders.add(currentHeader); keepColumnIndex.add(i); } } // 逐行读取数据 for (CSVRecord record : parser) { System.out.println("Record #: " + record.getRecordNumber()); // 按保留的索引读取列内容,自动跳过重复列 for (Integer index : keepColumnIndex) { String headerName = rawHeaderList.get(index); String cellValue = record.get(index); System.out.println(headerName + ": " + cellValue); } System.out.println("---"); } }
效果验证
针对你给出的表头示例 ID Name Email Email,上述逻辑会自动识别出索引位置3的Email列是重复项,只保留索引0(ID)、1(Name)、2(Email)三个列的内容,第二个重复的Email列不会被读取。
注意:如果你的业务需要保留最后一个出现的重复列、或者给重复列重命名(比如Email/Email1),只需要调整保留列索引的判定逻辑即可,不需要改动整体的解析流程。
版本兼容说明:
withAllowDuplicateHeaderNames是Commons CSV 1.8版本新增的配置,如果使用的是更早的旧版本,可先关闭withFirstRecordAsHeader()配置,手动读取第一行原始数据作为表头,再逐行做列值解析,整体逻辑完全一致。
内容的提问来源于stack exchange,提问作者duolanierduone
相关产品推荐
相关产品推荐

