Java实现.xlsx与.csv文件单元格值对比的技术求助
XLSX与CSV单元格逐位对比的实现方案
核心思路
把XLSX和CSV的行、单元格遍历整合到同一个双层循环中,同时处理两者行/列数不一致的边界情况,统一将单元格值转为字符串后再对比,避免类型差异导致的误判。
关键实现代码
确保项目已引入Apache POI和OpenCSV依赖,先导入必要包:
import org.apache.poi.ss.usermodel.*; import com.opencsv.CSVReader; import java.io.FileInputStream; import java.io.FileReader; import java.util.List;
1. XLSX单元格值统一转换工具方法
处理XLSX中不同类型的单元格(字符串、数字、日期、公式等),统一转为字符串格式:
private static String getCellValue(Cell cell) { if (cell == null) { return ""; } switch (cell.getCellType()) { case STRING: return cell.getStringCellValue().trim(); case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { // 可根据需求调整日期格式化规则 return cell.getDateCellValue().toString(); } else { // 避免数字转为科学计数法,直接转字符串 return String.valueOf(cell.getNumericCellValue()).trim(); } case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()).trim(); case FORMULA: // 计算公式结果并递归获取值 FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator(); return getCellValue(evaluator.evaluateInCell(cell)); default: return ""; } }
2. 主对比逻辑
将行遍历和单元格对比整合,覆盖所有行/列的对比场景:
public void compareXlsxAndCsv(String xlsxFilePath, String csvFilePath) { try (Workbook workbook = WorkbookFactory.create(new FileInputStream(xlsxFilePath)); CSVReader csvReader = new CSVReader(new FileReader(csvFilePath))) { Sheet xlsxSheet = workbook.getSheetAt(0); // 读取XLSX第一个工作表 List<String[]> csvRows = csvReader.readAll(); // 读取所有CSV行 // 取两者最大行数,确保遍历完所有行(包括其中一个文件行数更多的情况) int totalRows = Math.max(xlsxSheet.getLastRowNum() + 1, csvRows.size()); for (int rowIdx = 0; rowIdx < totalRows; rowIdx++) { Row xlsxRow = xlsxSheet.getRow(rowIdx); String[] csvRow = rowIdx < csvRows.size() ? csvRows.get(rowIdx) : new String[0]; // 取当前行的最大列数,处理列数不一致的情况 int totalCols = 0; if (xlsxRow != null) { totalCols = Math.max(totalCols, xlsxRow.getLastCellNum()); } totalCols = Math.max(totalCols, csvRow.length); // 逐单元格对比 for (int colIdx = 0; colIdx < totalCols; colIdx++) { // 获取XLSX单元格值 String xlsxVal = ""; if (xlsxRow != null) { Cell cell = xlsxRow.getCell(colIdx); xlsxVal = getCellValue(cell); } // 获取CSV单元格值 String csvVal = colIdx < csvRow.length ? csvRow[colIdx].trim() : ""; // 对比并输出差异 if (!xlsxVal.equals(csvVal)) { System.out.printf("差异位置:行%d,列%d%nXLSX值:%s%nCSV值:%s%n---%n", rowIdx + 1, colIdx + 1, xlsxVal, csvVal); } } } } catch (Exception e) { e.printStackTrace(); } }
注意事项
- 使用
try-with-resources自动关闭流,避免资源泄漏 - 对比前对所有值做
trim()处理,避免因首尾空格导致的误判 - 处理XLSX公式单元格时,默认取计算结果,若需对比公式可修改工具方法
- 若XLSX包含多个工作表,可在外层增加工作表遍历循环
内容的提问来源于stack exchange,提问作者f105thud
相关产品推荐
相关产品推荐

