[csv] is missing some elements to ease the use of headers. I have no clear idea on how to address this, here are my thoughts.

Headers are used when the fields are accessed by the column name rather than by the index. This provides some flexibility because the input file can be slightly modified by reordering the columns or by inserting new columns without breaking the existing code.

Using the current API here is how one would work with headers:

  CSVParser parser = new CSVParser(in);
  Iterator<String[]> it = parser.iterator();

  // read the header
  String[] header = it.next();

  // build a name to index mapping
  Map<String, Integer> mapping = new HashMap<>();
  for (int i = 0; i < header.length; i++) {
      mapping.put(header[i], i);
  }

  // parse the records
  for (String[] record : parser) {
      Person person = new Person();
      person.setName(record[mapping.get("name")]);
      person.setEmail(record[mapping.get("email")]);
      person.setPhone(record[mapping.get("phone")]);
      persons.add(person);
  }

The user has to take care of the mapping, which is not very friendly. I have several solutions in mind:

1. Do nothing and address it in the next release with the bean mapping. Parsing the file would then look like this:

  CSVFormat<Person> format = CSVFormat.DEFAULT.withType(Person.class);
  for (Person person : format.parse(in)) {
      persons.add(person);
  }


2. Add a parser returning a Map instead of a String[]

  // declare the header in the format,
  // the header line will be parsed automatically
  CSVFormat format = CSVFormat.DEFAULT.withHeader();

  for (Map<String, String> record : new CSVMapParser(in, format))) {
      Person person = new Person();
      person.setName(record.get("name"));
      person.setEmail(record.get("email"));
      person.setPhone(record.get("phone"));
      persons.add(person);
  }


2bis. Have the same CSVParser class returning String[] or Map<String, String> depending on a generic parameter. Not sure it's possible with type erasure.


3. Have the parser maintain the name->index mapping. The parser read the first line automatically if the format declares a header, and a getColumnIndex() method is exposed.

  CSVFormat format = CSVFormat.DEFAULT.withHeader();
  CSVParser parser = new CSVParser(in, format);

  // parse the records
  for (String[] record : parser) {
      Person person = new Person();
      person.setName(record[parser.getColumnIndex("name")]);
      person.setEmail(record[parser.getColumnIndex("email")]);
      person.setPhone(record[parser.getColumnIndex("phone")]);
      persons.add(person);
  }


What do you think?

Emmanuel Bourg

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to