【问题标题】:CSVFormat add quotation to headerCSVFormat 在标题中添加引号
【发布时间】:2021-09-08 18:19:03
【问题描述】:

我正在使用 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 创建时,它只包含不带引号的标题。有谁知道如何解决它?我知道我使用字符串数组作为标题,但我想避免这种情况,因为我有很多值,字符串会变得很长。

【问题讨论】:

    标签: java apache-commons-csv


    【解决方案1】:

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

    CSVPrinter printer = new CSVPrinter(new FileWriter(outFile), CSVFormat.DEFAULT.withHeader("\"FILENAME\"", "\"TEST\""));
    

    【讨论】:

    • 好的,谢谢你的回答,我想避免这个解决方案,但如果枚举不可能,我必须处理它。
    【解决方案2】:

    正如 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,它是反向做的,但技巧仍然适用。


    【讨论】:

    • 好的,谢谢,几乎解决了我的解决方案,唯一的问题是我的输出有三个 " 而不是一个。
    • @user15980267,我编辑了答案以解决您的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多