2

我正在使用 apache.commons.csv 创建一个 CSV 文件。生成文件时,我想用该方法解析一个标题.withHeader()。我解析的值应该有像“FILENAME”这样的引号。为此,我想使用枚举类。但是,我不太确定在名称周围添加引号是如何工作的。我测试了它并使用该代码:

    private enum Header{
        FILENAME("\"FILENAME\""), 
        TEST("\"Test\"");
    
        private final String string;
    
        Header(String string){
            this.string = string;
        }
    }

    public void addHeader(File outFile) throws IOException{
            CSVPrinter printer = new CSVPrinter(outFile, CSVFormat.DEFAULT.withHeader(Header.class));
    }

但是,当outfile创建它时,它只包含不带引号的标题。有谁知道如何解决它?我知道我使用字符串数组作为标题,但我想避免这种情况,因为我有很多值,字符串会变得很长。

4

2 回答 2

1

这是因为它的withHeader(Header.class)实现方式,它使用 Enums 的.name()方法将枚举值作为字符串获取,从而将实际的枚举值获取为 string: FILENAMEnot "\"FILENAME\""。要在 csv 中获取双引号,您可以使用这样的字符串数组:

CSVPrinter printer = new CSVPrinter(new FileWriter(outFile), CSVFormat.DEFAULT.withHeader("\"FILENAME\"", "\"TEST\""));
于 2021-06-28T06:59:13.493 回答
1

正如 George Nechifor 所建议的,我们可以使用CSVFormat#withHeader(String...)以获得更好的灵活性。为了避免重复和硬编码,我们当然应该使用来自枚举的值,并进行简单的映射。

Arrays.stream(Header.values()).map(Header::getCsvHeader).toArray(String[]::new)

并将导致
"""FILENAME""","""Test"""
一个可运行的示例如下(使用 apache commons-csv 1.8):

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;

public class CsvWithEnumHeader {
    public static void main(String[] args) throws IOException {
        addHeader(new File("C://temp/demo.csv"));
    }

    public static void addHeader(File outFile) throws IOException {
        // apache common csv 1.8 cannot compile with new CSVPrinter(outFile,...)
        try (CSVPrinter printer = new CSVPrinter(new FileWriter(outFile),
                CSVFormat.DEFAULT.withHeader(Arrays.stream(Header.values()).map(Header::getCsvHeader).toArray(String[]::new)))) {
        }
    }
}
public enum Header {
    FILENAME("\"FILENAME\""),
    TEST("\"Test\"");

    private final String csvHeader;

    Header(String csvHeader) {
        this.csvHeader = csvHeader;
    }

    public String getCsvHeader() {
        return csvHeader;
    }
}

从评论更新

似乎OP想要的是标题被引用而不是包含双引号的标题。我们可能withQuoteMode(QuoteMode.ALL)\"getCsvHeader.

CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL).withHeader(Arrays.stream(Header.values()).map(Header::getCsvHeader).toArray(String[]::new)))

结果将是
"FILENAME","Test"
请注意,这也会引用 csv 中的记录。如果我们只想引用标头,请参考CSVPrinter remove quotes only from header,这是以相反的方式进行的,但技巧仍然适用。


于 2021-06-28T13:55:01.817 回答