1

Be gentle, This is my first time using Apache Commons CSV 1.7.

I am creating a service to process some CSV inputs, add some additional information from exterior sources, then write out this CSV for ingestion into another system.

I store the information that I have gathered into a list of HashMap<String, String> for each row of the final output csv. The Hashmap contains the <ColumnName, Value for column>.

I have issues using the CSVPrinter to correctly assign the values of the HashMaps into the rows. I can concatenate the values into a string with commas between the variables; however, this just inserts the whole string into the first column.

I cannot define or hardcode the headers since they are obtained from a config file and may change depending on which project uses the service.

Here is some of my code:

try (BufferedWriter writer = Files.newBufferedWriter(
    Paths.get(OUTPUT + "/" + project + "/" + project + ".csv"));)
{
    CSVPrinter csvPrinter = new CSVPrinter(writer,
        CSVFormat.RFC4180.withFirstRecordAsHeader());
    csvPrinter.printRecord(columnList);

for (HashMap<String, String> row : rowCollection)
{
    //Need to map __record__ to column -> row.key, value -> row.value for whole map.

    csvPrinter.printrecord(__record__);
}

csvPrinter.flush();

}

Thanks for your assistance.

DwB
  • 37,124
  • 11
  • 56
  • 82
ManxDev
  • 98
  • 2
  • 12
  • columnList contains the list of headers, right ? – b.GHILAS Nov 27 '19 at 12:31
  • Please provide a [mcve] – Pitto Nov 27 '19 at 12:35
  • Does this answer your question? [Write CSV from List of HashMaps with Header using Apache Commons CSV](https://stackoverflow.com/questions/55186696/write-csv-from-list-of-hashmaps-with-header-using-apache-commons-csv) – trilogy Jul 28 '22 at 18:13

2 Answers2

1

You actually have multiple concerns with your technique;

  1. How do you maintain column order?
  2. How do you print the column names?
  3. How do you print the column values?

Here are my suggestions.

  1. Maintain column order. Do not use HashMap, because it is unordered. Instead, use LinkedHashMap which has a "predictable iteration order" (i.e. maintains order).

  2. Print column names. Every row in your list contains the column names in the form of key values, but you only print the column names as the first row of output. The solution is to print the column names before you loop through the rows. Get them from the first element of the list.

  3. Print column values. The "billal GHILAS" answer demonstrates a way to print the values of each row.

Here is some code:

try (BufferedWriter writer = Files.newBufferedWriter(
     Paths.get(OUTPUT + "/" + project + "/" + project + ".csv"));)
{
    CSVPrinter csvPrinter = new CSVPrinter(writer,
        CSVFormat.RFC4180.withFirstRecordAsHeader());

    // This assumes that the rowCollection will never be empty.
    // An anonymous scope block just to limit the scope of the variable names.
    {
        HashMap<String, String> firstRow = rowCollection.get(0);
        int valueIndex = 0;
        String[] valueArray = new String[firstRow.size()];
        
        for (String currentValue : firstRow.keySet())
        {
            valueArray[valueIndex++] = currentValue;
        }

        csvPrinter.printrecord(valueArray);
    }

    for (HashMap<String, String> row : rowCollection)
    {
        int valueIndex = 0;
        String[] valueArray = new String[row.size()];
        
        for (String currentValue : row.values())
        {
            valueArray[valueIndex++] = currentValue;
        }

        csvPrinter.printrecord(valueArray);
    }

    csvPrinter.flush();
}
trilogy
  • 1,738
  • 15
  • 31
DwB
  • 37,124
  • 11
  • 56
  • 82
  • Thank you for this answer. I have implemented a slightly different solution to what is listed above, purely because it suits my particular issue better than the above - not because this is incorrect. Marked as accepted in the hope it aids other in the future with a similar problem. – ManxDev Dec 03 '19 at 09:39
0
for (HashMap<String,String> row : rowCollection) {
       Object[] record = new Object[row.size()];
       for (int i = 0; i < columnList.size(); i++) {
            record[i] = row.get(columnList.get(i));
       }

       csvPrinter.printRecord(record);
 }
b.GHILAS
  • 2,273
  • 1
  • 8
  • 16