Java导出分号分隔CSV时如何在StringBuilder中正确插入分号
实现方案
方案1:直接修改现有代码(无需引入第三方依赖)
原有代码的核心问题是全局判断StringBuilder长度加空格分隔符,没有按行做拆分控制,无法实现行尾无多余分隔符的需求,同时未兼容不同单元格类型的读取逻辑,遇到数字/日期类型单元格会直接报错。修改后代码如下:
public void download() throws IOException { List<FileDTO> tests = testService.getTestFileDtoList(); XSLXManagerTestExporter excelExporter = new XSLXManagerTestExporter(tests); XSSFWorkbook workBook = excelExporter.export(); XSSFSheet selSheet = workBook.getSheet("sheet"); StringBuilder sb = new StringBuilder(); // 定义分隔符常量,后续调整方便 final String SEPARATOR = "; "; for (int i = 0; i <= selSheet.getLastRowNum(); i++) { XSSFRow row = selSheet.getRow(i); if (row == null) continue; // 行内单元格计数,控制行首不加分隔符、行尾不留多余分隔符 int cellCnt = 0; Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); if (cellCnt > 0) { sb.append(SEPARATOR); } // 兼容不同单元格类型读取,避免类型不匹配报错 String cellValue; switch (cell.getCellType()) { case STRING: cellValue = cell.getStringCellValue(); break; case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { cellValue = new SimpleDateFormat("MM/dd/yyyy").format(cell.getDateCellValue()); } else { cellValue = String.valueOf(cell.getNumericCellValue()); } break; case BOOLEAN: cellValue = String.valueOf(cell.getBooleanCellValue()); break; default: cellValue = ""; } sb.append(cellValue); cellCnt++; } // 每行结束加换行符 sb.append("\n"); } workBook.close(); // 指定UTF-8编码避免乱码 writeBytesToFileApache(sb.toString().getBytes(StandardCharsets.UTF_8)); } private static void writeBytesToFileApache(byte[] bytes) throws IOException { FileUtils.writeByteArrayToFile(new File(".....\\file.csv"), bytes); }
修改后即可直接实现分号分隔、行尾无多余分号的需求。
方案2:使用专业CSV处理库(推荐,兼容特殊字符场景)
如果业务中存在单元格内容包含分号、换行、双引号等特殊字符的场景,建议用成熟的CSV处理库自动处理转义逻辑,避免CSV格式错乱,推荐使用OpenCSV。
首先引入依赖(Maven示例):
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> <!-- 可自行替换为最新稳定版 --> </dependency>
实现代码如下:
public void download() throws IOException { List<FileDTO> tests = testService.getTestFileDtoList(); XSLXManagerTestExporter excelExporter = new XSLXManagerTestExporter(tests); XSSFWorkbook workBook = excelExporter.export(); XSSFSheet selSheet = workBook.getSheet("sheet"); try (CSVWriter writer = new CSVWriter( new FileWriter(".....\\file.csv", StandardCharsets.UTF_8), ';', // 指定分隔符为分号 CSVWriter.NO_QUOTE_CHARACTER, // 不需要自动加引号可设置该参数,需要转义时可改为默认双引号 CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END )) { for (int i = 0; i <= selSheet.getLastRowNum(); i++) { XSSFRow row = selSheet.getRow(i); if (row == null) continue; List<String> cellValues = new ArrayList<>(); Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); cellValues.add(getCellValue(cell)); } writer.writeNext(cellValues.toArray(new String[0])); } } finally { workBook.close(); } } // 抽取公共的单元格值读取方法 private String getCellValue(Cell cell) { if (cell == null) return ""; switch (cell.getCellType()) { case STRING: return cell.getStringCellValue(); case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { return new SimpleDateFormat("MM/dd/yyyy").format(cell.getDateCellValue()); } else { return String.valueOf(cell.getNumericCellValue()); } case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); default: return ""; } }
内容的提问来源于stack exchange,提问作者mat373
相关产品推荐
相关产品推荐

