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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:15:03