dmachop
dmachop

Reputation: 884

Apache CSV - Convert List<String> to CSVRecord

I'm inclined to use CSVRecord because it can be used to map with a header and get the corresponding value. My application frequently uses CSVRecord class. However, I cannot instantiate the CSVRecord. I would prefer not to modify the source/create a new class since it already provides a parser that returns CSVRecord. I have got a list of strings (header as well as the values) that needed to be converted to the CSVRecord type. Is there a direct way that this can be done without going around with formatting and then parsing back? Like the one below:

private CSVRecord format(List<String> header, List<String> values)
{
    CSVFormat csvFormat = CSVFormat.DEFAULT.withRecordSeparator(System.lineSeparator())
            .withQuoteMode(QuoteMode.ALL);
    CSVRecord csvRecord = null;
    final StringWriter out = new StringWriter();
    try (CSVPrinter csvPrinter = new CSVPrinter(out, csvFormat);)
    {
        csvPrinter.printRecord(values);
        String value = out.toString().trim();
        for (CSVRecord r : CSVParser.parse(value, csvFormat.withHeader(header.toArray(new String[header.size()]))))
            csvRecord = r;
    }
    catch (IOException e)
    {
        logger.error("Unable to format the Iterable to CSVRecord. Header: [{}]; Values: [{}]", e,
                String.join(", ", header), String.join(", ", values));
    }
    return csvRecord;
}

private void testMethod() throws Exception
{
    List<String> header = Arrays.asList("header1", "header2", "header3");
    List<String> record = Arrays.asList("val1", "val2", "val3");
    CSVRecord csvRecord = format(header, record);
    logger.info("{}", csvRecord.get("header2"));
}

Upvotes: 4

Views: 8589

Answers (2)

Berkley Lamb
Berkley Lamb

Reputation: 293

You could pass the list as a string directly into the CSVParser instead of creating a writer.

CSVRecord csvr = CSVParser.parse(
values.stream().collect(Collectors.joining(","))
,csvFormat.withHeader(header.toArray(new String[header.size()])))
.getRecords().get(0);

Upvotes: 4

Mark Ashworth
Mark Ashworth

Reputation: 184

The BeanIO and SimpleFlatMapper are way better at solving this problem. BeanIO uses a Map data structure and a config file to declare how the CSV file should be structured so it is very powerful. SimpleFlatMapper will take you POJO properties as the heading names by default and output the property values are column values.

BeanIO

http://beanio.org/2.1/docs/reference/index.html#CSVStreamFormat

SimpleFlatMapper

http://simpleflatmapper.org/

CsvParser
   .mapTo(MyObject.class)
   .stream(reader)
   .forEach(System.out::println);

Upvotes: 1

Related Questions