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

如何用Jackson实现CSV文件中指定ID行的删除与新增

要实现这个逻辑,核心是先读取CSV所有内容,过滤掉冲突的id行,再合并新数据后重新写入——因为CSV是纯文本文件,没法直接修改某一行,只能全量读写。

具体实现步骤

  • 读取现有CSV的所有数据(包括表头)
  • 将传入的新数据按id构建Map,快速判断哪些id需要替换
  • 过滤原有数据:保留那些id不在新数据Map中的行
  • 合并过滤后的旧数据 + 新数据,重新写入CSV(覆盖原文件,不是追加)

修改后的代码实现

确保你的EmpData类有getId()方法(用来匹配唯一标识),然后修改addOrUpdate方法:

public static void addOrUpdate(File file, List<EmpData> newData) {
    CsvMapper mapper = new CsvMapper();
    mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true);
    CsvSchema schema = mapper.schemaFor(EmpData.class)
            .withColumnSeparator(',')
            .withHeader(); // 明确使用表头,避免数据错位

    try {
        // 1. 读取现有CSV数据(文件不存在/为空时跳过)
        List<EmpData> existingData = new ArrayList<>();
        if (file.exists() && file.length() > 0) {
            ObjectReader reader = mapper.readerFor(EmpData.class).with(schema);
            existingData = reader.<EmpData>readValues(file).readAll();
        }

        // 2. 将新数据按id分组,快速判断重复
        Map<Integer, EmpData> newDataMap = newData.stream()
                .collect(Collectors.toMap(EmpData::getId, data -> data));

        // 3. 过滤现有数据:移除和新数据id重复的行
        List<EmpData> filteredData = existingData.stream()
                .filter(data -> !newDataMap.containsKey(data.getId()))
                .collect(Collectors.toList());

        // 4. 合并旧数据(过滤后)和新数据
        filteredData.addAll(newData);

        // 5. 重新写入CSV(覆盖原文件,而非追加)
        ObjectWriter writer = mapper.writerFor(EmpData.class).with(schema);
        try (OutputStream os = new FileOutputStream(file)) {
            writer.writeValues(os).writeAll(filteredData);
        }

    } catch (IOException e) {
        throw new RuntimeException("处理CSV文件失败", e);
    }
}

关键细节说明

  • 表头处理:withHeader()确保读写时都识别表头,避免字段顺序错乱
  • 文件兼容性:处理了文件不存在、空文件的情况,直接写入新数据即可
  • 覆盖写入:去掉了FileOutputStream的true参数,改为覆盖原文件,彻底避免重复数据
  • 性能优化:用Map存储新数据的id,判断重复的时间复杂度从O(n*m)降到O(n),数据量大时更高效
  • 资源安全:用try-with-resources自动关闭OutputStream,避免资源泄漏

额外注意事项

  • 如果你的id不是Integer类型,把Map的key类型改成对应类型(比如String)
  • 如果CSV有特殊格式需求(比如引号包裹字段、换行符),可以调整CsvSchema的配置(如withQuoteChar('"'))
  • 大文件场景:如果CSV文件非常大,全量读写可能内存不足,这时可以考虑逐行读取+写入临时文件,最后替换原文件

内容的提问来源于stack exchange,提问作者ppb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:43:22