如何在univocity中结合BatchedColumnProcessor使用列映射
在Univocity中使用BatchedColumnProcessor实现列映射
BatchedColumnProcessor并没有像BeanListProcessor那样提供直接的setColumnMapping()方法,因为它的核心设计是按列批量收集数据,而非直接映射到JavaBean。要实现自定义列映射,你需要手动维护列名/索引的映射关系,并在批次处理逻辑中根据映射获取对应列的数据。
实现步骤与代码示例
1. 定义列映射关系
先明确CSV原始列名(或索引)与你自定义列标识的对应关系:
// 示例:CSV原始列名 -> 自定义列名的映射 Map<String, String> columnMapping = new HashMap<>(); columnMapping.put("product_id", "id"); columnMapping.put("product_name", "name"); columnMapping.put("product_price", "price");
如果CSV没有表头,按列索引映射:
// 示例:CSV列索引 -> 自定义列名的映射 Map<Integer, String> indexMapping = new HashMap<>(); indexMapping.put(0, "id"); indexMapping.put(1, "name"); indexMapping.put(2, "price");
2. 配置解析器与自定义BatchedColumnProcessor
启用表头提取(如果CSV包含表头),然后在处理器中利用映射关系处理批次数据:
CsvParserSettings settings = new CsvParserSettings(); // 启用表头提取(CSV第一行作为表头时开启) settings.setHeaderExtractionEnabled(true); // 初始化批次处理器,设置每批处理5行 BatchedColumnProcessor processor = new BatchedColumnProcessor(5) { // 存储自定义列名到CSV列索引的映射 private Map<String, Integer> customColumnIndexMap; @Override public void processStarted(ParsingContext context) { super.processStarted(context); // 获取CSV的原始表头 String[] originalHeaders = context.headers(); customColumnIndexMap = new HashMap<>(); // 构建自定义列名到列索引的映射表 for (int i = 0; i < originalHeaders.length; i++) { String originalName = originalHeaders[i]; // 用自定义映射替换,没有映射则保留原始列名 String customName = columnMapping.getOrDefault(originalName, originalName); customColumnIndexMap.put(customName, i); } } @Override public void batchProcessed(int rowsInThisBatch) { super.batchProcessed(rowsInThisBatch); // 获取当前批次的列数据(键为CSV原始表头名) Map<String, List<Object>> batchData = getColumnValuesAsMapOfNames(); // 通过自定义映射获取目标列的数据 List<Object> idList = batchData.get(columnMapping.get("product_id")); List<Object> nameList = batchData.get(columnMapping.get("product_name")); List<Object> priceList = batchData.get(columnMapping.get("product_price")); // 编写你的批次处理逻辑,比如转换为对象、存储到数据库等 for (int i = 0; i < rowsInThisBatch; i++) { String productId = (String) idList.get(i); String productName = (String) nameList.get(i); BigDecimal productPrice = (BigDecimal) priceList.get(i); // 处理数据... } // 清空当前批次数据,避免影响下一批次 reset(); } }; settings.setProcessor(processor); CsvParser parser = new CsvParser(settings); // 执行解析(示例:解析本地CSV文件) parser.parse(new FileReader("your-products.csv"));
关键说明
- 如果CSV无表头,可直接通过
getColumnValuesAsList()按索引获取数据,结合预先定义的indexMapping关联自定义列名。 getColumnValuesAsMapOfNames()返回的是当前批次的列数据,键为CSV原始表头名,因此需要通过自定义映射转换为你需要的标识。- 批次处理完成后必须调用
reset(),否则下一批次会累积之前的数据。
内容的提问来源于stack exchange,提问作者Salman S
相关产品推荐
相关产品推荐

