Search code examples
javaapache-commons-csv

CSVFormat add quotation to header


I am using apache.commons.csv to create a CSV file. When generating the file ,I want to parse a header with the method .withHeader(). The values I parse should have quotes like "FILENAME". To do that I want to use an enum class. However I am not quite sure how it works to add quotes around the name. I tested it and with that code:

    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));
    }

However when outfile is created it only contains the header without quotes. Does anyone have an idea how to solve it? I know I use a string array as header but I would like to avoid that, because I have a lot of values an the string would get quite long.


Solution

  • As suggested by George Nechifor, we can use CSVFormat#withHeader(String...) for better flexibility. To avoid duplication and hardcoding, of course we should use the value from enum, with a simple mapping.

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

    And will result in
    """FILENAME""","""Test"""
    An runnable example is as follows(with 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;
        }
    }
    

    Update from the comment

    it seems what OP want is the header get quoted instead of header containing double quote. We may use withQuoteMode(QuoteMode.ALL) and remove \" in getCsvHeader.

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

    The result will be
    "FILENAME","Test"
    Please note that this will also quote the record in csv. If we only want to quote the header, please refer to CSVPrinter remove quotes only from header, which is doing in reverse way, but the tricks still apply.