如何避免CSVFormat中逗号前的反斜杠

How to avoid backslash before comma in CSVFormat

我正在 java 中使用 CSVFormat 创建一个 CSV 文件,我在 header 和值中都面临的问题是每当字符串很长并且有逗号 api 总是在逗号前插入一个 \ 。结果,header 没有正确形成,csv 文件中的值正在为 .我正在发布我所做的代码

   try (CSVPrinter csvPrinter = new CSVPrinter(out,
            CSVFormat.DEFAULT.withHeader("\""+SampleEnum.MY_NAME.getHeader()+"\"", "\""+SampleEnum.MY_TITLE.getHeader()+"\"",
                    "\""+SampleEnum.MY_ID.getHeader()+"\"", "\""+SampleEnum.MY_NUMBER.getHeader()+"\"", "\""+SampleEnum.MY_EXTERNAL_KEY.getHeader()+"\"",
                    "\""+SampleEnum.DATE.getHeader()+"\"","\""+SampleEnum.MY_ACTION.getHeader()+"\"",
                    "\"\"\""+SampleEnum.MY__DEFI.getHeader()+"\"\"\"", SampleEnum.MY_ACTION.getHeader(),
                    SampleEnum.CCHK.getHeader(), SampleEnum.DISTANCE_FROM_LOCATION.getHeader(),
                    SampleEnum.TCOE.getHeader(), SampleEnum.HGTR.getHeader(),SampleEnum._BLANK.getHeader(),
                    SampleEnum.LOCATION_MAP.getHeader(), SampleEnum.SUBMISSION_ID.getHeader())                      
                    .withDelimiter(',').withEscape('\').withQuote('"').withTrim().withQuoteMode(QuoteMode.MINIMAL)
    )) {
        sampleModel.forEach(sf -> {
            try {
                csvPrinter.printRecord(sf.getMyName(),
                        sf.getMyTitle(),
                        sf.getMyID(),
                        sf.getMyNo(),

所以现在的问题是我得到这样的输出

"\"Name:\"","\"Title\"","\"ID #:\"","\"Store #:\"","\"Store #: External Key\"","\"Date:\"","\"\"\"It's performance  issue in detail to include dates,times, circumstances, etc.\"\"\""

我在每个逗号之前得到 \,当它出现在值中时,文本的下一部分将转移到下一个单元格。

我需要的输出是

"Name:","Title:","Employee ID #:","Store #:","Store #: CurrierKey","Date:","Stage of Disciplinary Action:","""Describe your view about the company, times, circumstances, etc.""",

我在努力 https://commons.apache.org/proper/commons-csv/jacoco/org.apache.commons.csv/CSVFormat.java.html link,但我无法理解该修复程序。请帮忙。

发生这种情况是因为您使用的 QuoteMode.NONE 具有以下 Javadoc:

Never quotes fields. When the delimiter occurs in data, the printer prefixes it with the escape character. If the escape character is not set, format validation throws an exception.

您可以使用 QuoteMode.MINIMAL 仅引用包含特殊字符的字段(例如字段分隔符、引号字符或行分隔符字符串的字符)。


我建议您使用 CSVFormat.DEFAULT,如果您不能使用其他格式之一,然后自行配置所有内容。检查反斜杠 (\) 是否真的是您用例的正确转义字符。通常它是双引号 (")。此外,您可能希望从 header 定义中删除所有双引号,因为它们会根据您的配置自动添加(如有必要)。

StringBuilder out = new StringBuilder();
try (CSVPrinter csvPrinter = new CSVPrinter(out,
        CSVFormat.DEFAULT
                .withHeader("AAAA", "BB\"BB", "CC,CC", "DD'DD")
                .withDelimiter(',')
                .withEscape('\') // <- maybe you want '"' instead
                .withQuote('"').withRecordSeparator('\n').withTrim()
                .withQuoteMode(QuoteMode.MINIMAL)
)) {
    csvPrinter.printRecord("WWWW", "XX\"XX", "YY,YY", "ZZ'ZZ");
}
System.out.println(out);
AAAA,"BB\"BB","CC,CC",DD'DD
WWWW,"XX\"XX","YY,YY",ZZ'ZZ

在您的 edit 之后,您似乎希望所有字段都用双引号作为转义字符引用。因此,您可以像这样使用 QuoteMode.ALL.withEscape('"')

StringBuilder out = new StringBuilder();
try (CSVPrinter csvPrinter = new CSVPrinter(out,
        CSVFormat.DEFAULT
                .withHeader("AAAA", "BB\"BB", "CC,CC", "\"DD\"", "1")
                .withDelimiter(',')
                .withEscape('"')
                .withQuote('"').withRecordSeparator('\n').withTrim()
                .withQuoteMode(QuoteMode.ALL)
)) {
    csvPrinter.printRecord("WWWW", "XX\"XX", "YY,YY", "\"DD\"", "2");
}
System.out.println(out);
"AAAA","BB""BB","CC,CC","""DD""","1"
"WWWW","XX""XX","YY,YY","""DD""","2"

在您的 comment 中,您声明只在需要时使用双引号,而只在一个字段中使用三引号。然后,您可以按照第一个示例中的建议使用 QuoteMode.MINIMAL.withEscape('"')。当您用双引号括起该字段的输入时会生成三重引号(一次是因为有一个特殊字符并且需要引用该字段,第二个是因为您添加了明确的 " 第三个是那里可以逃避你的明确引用)。

StringBuilder out = new StringBuilder();
try (CSVPrinter csvPrinter = new CSVPrinter(out,
        CSVFormat.DEFAULT
                .withHeader("AAAA", "BB\"BB", "CC,CC", "\"DD\"", "1")
                .withDelimiter(',')
                .withEscape('"')
                .withQuote('"').withRecordSeparator('\n').withTrim()
                .withQuoteMode(QuoteMode.MINIMAL)
)) {
    csvPrinter.printRecord("WWWW", "XX\"XX", "YY,YY", "\"DD\"", "2");
}
System.out.println(out);
AAAA,"BB""BB","CC,CC","""DD""",1
WWWW,"XX""XX","YY,YY","""DD""",2

根据 chat,您希望在 header 有引号和没有引号时完全控制。 QuoteMode 和转义字符的组合无法提供所需的结果。因此,我建议您手动构造 header:

StringBuilder out = new StringBuilder();
try (CSVPrinter csvPrinter = new CSVPrinter(out,
        CSVFormat.DEFAULT
                .withDelimiter(',').withEscape('"')
                .withQuote('"').withRecordSeparator('\n').withTrim()
                .withQuoteMode(QuoteMode.MINIMAL))
) {
    out.append(String.join(",", "\"AAAA\"", "\"BBBB\"", "\"CC,CC\"", "\"\"\"DD\"\"\"", "1"));
    out.append("\n");
    csvPrinter.printRecord("WWWW", "XX\"XX", "YY,YY", "\"DD\"", "2");
}
System.out.println(out);
"AAAA","BBBB","CC,CC","""DD""",1
WWWW,"XX""XX","YY,YY","""DD""",2