0

OpenCSV is a java library for reading and writing CSV files. I want to read a CSV file and extract the header of the CSV file before handling the data records. How to do this?

This is my current code and where I need the header information:

BufferedReader in = new BufferedReader(new InputStreamReader(file.getInputStream()));

CSVParser csvParser = new CSVParserBuilder().withSeparator('\t').build();

CSVReader csvReader = new CSVReaderBuilder(in).withCSVParser(csvParser).build();

// The code that follows depends on the column names, so
// I want to get the header information here so I can
// discover if I have to map to the Book entity class or to another one.

CsvToBean<Book> csvToBeanConverter = new CsvToBeanBuilder<Book>(csvReader).withType(Book.class).build();

Iterator<Book> bookIter = csvToBeanConverter.iterator();

bookIter.forEachRemaining(book -> {
    System.out.println("book: " + book);
});

UPDATE 1:
I start to think that the two "standard" solutions OpenCSV and apache-commons-csv both have their weaknesses, so feel free to tell me your favorite CSV libraries. Put them into comments, not answers, because it's opinionated information by definition.

UPDATE 2:
How to read CSV headers and get them in to a list in java is only a workaround-grade solution for this question, because for making it work together with CsvToBean it involves mark() and reset() on the BufferedReader and therefor it limits the possible header size, throwing an exception if exceeded. See my answer for for details.

Daniel S.
  • 6,458
  • 4
  • 35
  • 78
  • Does this answer your question? [How to read CSV headers and get them in to a list in java](https://stackoverflow.com/questions/37519915/how-to-read-csv-headers-and-get-them-in-to-a-list-in-java) – akortex Jun 21 '22 at 09:49
  • @akortex Not really. Only as a workaround, because when you do, then the CsvToBean does not get to know the header and then fails to do the mapping. As a workaround you can mark() and reset() the BufferedReader so that the header information is still available to the CsvToBean class so it can read it again a second time. That feels kind of ugly. I'll nevertheless post the workaround as an answer. – Daniel S. Jun 21 '22 at 10:11

1 Answers1

0

As a workaround you can use header = csvReader.readNext() before creating the CsvToBean. However, you have to mark() and reset() the BufferedReader so that the header information can be read again by the CsvToBean class in order to do its mapping.
Note that this limits the size of the allowed header to the buffer size of the BufferedReader and throws an exception in reset() if this size is exceeded.

Here is the code:

BufferedReader in = new BufferedReader(new InputStreamReader(file.getInputStream()));

CSVParser csvParser = new CSVParserBuilder().withSeparator('\t').build();

CSVReader csvReader = new CSVReaderBuilder(in).withCSVParser(csvParser).build();

in.mark(8192);
String[] header = csvReader.readNext();
in.reset();
System.out.println("header: " + Arrays.toString(header));

CsvToBean<Book> csvToBeanConverter = new CsvToBeanBuilder<Book>(csvReader).withType(Book.class).build();

Iterator<Book> bookIter = csvToBeanConverter.iterator();

bookIter.forEachRemaining(book -> {
    System.out.println("book: " + book);
});
Daniel S.
  • 6,458
  • 4
  • 35
  • 78