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

按指定格式写入CSV异常:最后一行缺失竖线问题排查

我来帮你排查并解决这个竖线分隔CSV的格式异常问题,咱们一步步梳理:


需求目标

我们需要生成符合以下格式的竖线分隔CSV:

Redemption Reference Code|Status|Delivery company|Shipper Tracking Number|Comments
2006995040|Shipped|USPS|ABCD12345|Order SHIPPED
2006995042|Cancelled|||INVALID Address
2006995048|Ordered|USPS|ABCD12345|Order SHIPPED

当前实现代码

1. 订单数据收集逻辑

private void accumulateOrdersFromPlacement(){
    int count = 0;
    for (int i = 0; i < orderIds.size(); i++) {
        if (count == 0) {
            outPutLineData.add(orderIds.get(i));
            outPutLineData.add("Cancelled");
            outPutLineData.add("");
            outPutLineData.add(" ");
            outPutLineData.add(" ");
            cancelledStatusLineItems.add(orderIds.get(i));
            count++;
        } else if (count == 1) {
            outPutLineData.add(orderIds.get(i));
            outPutLineData.add("Shipped");
            if (outPutLineData.contains("Shipped")) {
                outPutLineData.add("USPS");
                outPutLineData.add("order SHIPPED");
                outPutLineData.add("");
            }
            shippedStatusLineItems.add(orderIds.get(i));
            count++;
        } else if (count == 2) {
            outPutLineData.add(orderIds.get(i));
            outPutLineData.add("No Longer Available");
            outPutLineData.add("");
            outPutLineData.add(" ");
            outPutLineData.add(" ");
            count++;
            nlaStatusLineItems.add(orderIds.get(i));
        } else if (count == 3) {
            outPutLineData.add(orderIds.get(i));
            outPutLineData.add("Ordered");
            outPutLineData.add("");
            outPutLineData.add(" ");
            outPutLineData.add(" ");
            orderedStatusLineItems.add(orderIds.get(i));
            count = 0;
        }
    }
}

2. 文件生成逻辑

private File createFile(final File directory) {
    FileWriter fw = null;
    File tempFile = null;
    try {
        directory.mkdir();
        tempFile = new File(".//FidelityFulfillment//" + generateFileName(countyThreeLetterCode, "FidelityFulfillment", ".csv", date));
        logReport(GenericConstants.NEW_LINE + "Fulfillment file creating:", tempFile.getName());
        fw = new FileWriter(tempFile, true);
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile, true))) {
            writer.write(generateHeaderLine());
            writer.newLine();
            for (int y = 1; y < outPutLineData.size(); y++) {
                if (y % 5 < 4) {
                    writer.write(outPutLineData.get(y-1) + fieldSeperator);
                    logReport(outPutLineData.get(y - 1) + fieldSeperator);
                } else {
                    writer.write(outPutLineData.get(y-1));
                    logReport(outPutLineData.get(y));
                }
                if (y % 5 == 0) {
                    writer.newLine();
                    logReport("newline");
                }
            }
            writer.close();
        } catch (final IOException e) {
            e.printStackTrace();
            final String err = "Unable to write file due to : " + e;
            logReport(GenericConstants.NEW_LINE + "Unable to create temp local File");
        } finally {
            fw.close();
        }
    }catch (Exception e){
        e.printStackTrace();
    }
    return tempFile;
}

问题现象

实际输出的CSV存在格式异常,最后一行缺失竖线,字段不完整:

Redemption Reference Code|Status|Delivery company|ShipperTrackingNumber|Comments
2006964032|Cancelled|| | 
newline
2006964034|Shipped|USPS|| 
newline
2006964036|No Longer Available|| 

问题排查与修复

1. 核心问题分析

文件生成的循环逻辑存在两个致命问题:

  • 遗漏最后一个元素:循环条件y < outPutLineData.size()导致最后一个元素(索引size-1)永远不会被写入,直接造成最后一行字段缺失
  • 字段分隔逻辑混乱:用y%5 <4判断是否加分隔符的逻辑,在处理非5的整数倍元素时,会导致最后一行的分隔符不完整

另外还有一个次要问题:代码中创建了重复的FileWriter,既容易导致资源泄露,也可能造成文件追加异常。

2. 修复方案

方案一:重构文件生成的循环逻辑

把循环改成按字段遍历,确保每个元素都被处理,并且每行的5个字段严格用竖线分隔:

// 替换原有的循环代码
for (int i = 0; i < outPutLineData.size(); i++) {
    String field = outPutLineData.get(i);
    // 不是当前行最后一个字段,就添加分隔符
    if ((i + 1) % 5 != 0) {
        writer.write(field + fieldSeperator);
        logReport(field + fieldSeperator);
    } else {
        // 当前行最后一个字段,直接写入后换行
        writer.write(field);
        logReport(field);
        writer.newLine();
        logReport("newline");
    }
}

方案二:清理冗余代码与优化

  • 去掉重复的FileWriter fw,用try-with-resources自动管理资源
  • 用directory.mkdirs()代替mkdir(),确保父目录不存在时也能创建成功
  • 移除accumulateOrdersFromPlacement中多余的if (outPutLineData.contains("Shipped"))判断(刚添加的元素必然存在,逻辑冗余)

修复后的完整createFile方法:

private File createFile(final File directory) {
    File tempFile = null;
    try {
        // 确保所有父目录都能被创建
        directory.mkdirs();
        tempFile = new File(".//FidelityFulfillment//" + generateFileName(countyThreeLetterCode, "FidelityFulfillment", ".csv", date));
        logReport(GenericConstants.NEW_LINE + "Fulfillment file creating:", tempFile.getName());
        
        // try-with-resources自动关闭writer,无需手动调用close
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))) {
            writer.write(generateHeaderLine());
            writer.newLine();
            
            // 遍历所有字段,按每行5个字段处理
            for (int i = 0; i < outPutLineData.size(); i++) {
                String field = outPutLineData.get(i);
                if ((i + 1) % 5 != 0) {
                    writer.write(field + fieldSeperator);
                    logReport(field + fieldSeperator);
                } else {
                    writer.write(field);
                    logReport(field);
                    writer.newLine();
                    logReport("newline");
                }
            }
        } catch (final IOException e) {
            e.printStackTrace();
            String err = "Unable to write file due to : " + e;
            logReport(GenericConstants.NEW_LINE + err);
        }
    } catch (Exception e) {
        e.printStackTrace();
        logReport(GenericConstants.NEW_LINE + "Failed to create file: " + e.getMessage());
    }
    return tempFile;
}

3. 验证效果

修复后,生成的CSV每行都会严格包含5个字段,用4个竖线分隔,不会出现最后一行缺失竖线或字段的情况,完全符合需求格式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:45:14