Search code examples
javalistsupercsv

How to write a list to CSV with Super CSV


Exception in thread "main" org.supercsv.exception.SuperCsvException: The number of columns to be processed (229326) must match the number of CellProcessors (8):

I believe i may have to redo what im doing using supercsv as it may be easier in the long run however im open to any other suggestions. I simply want to write back to a csv file, i have a list with all the data in it however the ouput is like this

4350 02/06/2013 3965.21 0.0 0.0 0.0 0.0 0.0,
4698 02/06/2013 498.16 0.0 0.0 0.0 0.0 0.0, 
4992 02/06/2013 97.87 87.82 6.05 0.0 0.0 0.0,  
4441 02/06/2013 18.8 71.98 11.6 0.0 0.0 -42.5,  54092 02/06/2013 105.11 118.82 6.24 0.0 0.0 0.0,

I've managed to get the out put i want by replacing strings within the list however when it runs it hangs and i believe its due to how i'm writing back to the csv, i'm not sure, what else to do other than to write it back to the csv diffrently not using super csv. The error i get is

"1805","31/07/2013","-233.4","0.0","0.0","0.0","0.0","0.0"
"8054","31/07/2013","280.45","82.38","52.38","0.0","0.0","-200.0"The number of columns to be processed (1) must match the number of CellProcessors (8):

My witer class is as follows

package writer;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.supercsv.cellprocessor.FmtDate;
import org.supercsv.cellprocessor.ParseDouble;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvListWriter;
import org.supercsv.io.ICsvListWriter;
import org.supercsv.prefs.CsvPreference;


public class RentStatementsWriter {
public ArrayList rData;
private List<String> csvData;

char b = ',';

public RentStatementsWriter(ArrayList rentData)  {
    rData = rentData;
    ICsvListWriter listWriter = null;


    try{
        listWriter = new CsvListWriter(new FileWriter("rentl.csv"),CsvPreference.STANDARD_PREFERENCE);
        CellProcessor[] processors =new CellProcessor[]{
                new ParseInt(),
                new FmtDate("dd/MM/yyyy"),//
                new ParseDouble(),
                new ParseDouble(),
                new ParseDouble(),
                new ParseDouble(),
                new ParseDouble(),
                new ParseDouble(),

        };
        final String [] header = new String []{"_num", "End_Date", "bal_val","rval","cval","bf_val","aval","pval"};

        System.out.print("to string "+rData.toString().replaceFirst(" ", "\"").replaceAll("\\,"," \\,").replaceAll("  ", "").replaceAll(" ", "\"\\,\"").replaceAll("\"\\,\"\\,", "\"\n\""));
        csvData = Arrays.asList(rData.toString().replaceFirst(" ", "\"").replaceAll("\\,"," \\,").replaceAll("  ", "").replaceAll(" ", "\"\\,\"").replaceAll("\"\\,\"\\,", "\"\""));
        /*
         * replace
         * .replaceAll(" ", "\"\\,\"")
         */
        listWriter.writeHeader(header);
        listWriter.write(csvData, processors);



    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        System.out.print(e+" file unable to write");
    } finally {
        if(listWriter !=null){
            try {
                listWriter.close();
            } catch (IOException e) {

                e.printStackTrace();
                System.out.println("list writer");
            }
        }

    }


}
String listToCsv(List<String> listOfStrings, char separator) {
    StringBuilder sb = new StringBuilder();

    // all but last
    for(int i = 0; i < listOfStrings.size() - 1 ; i++) {
        sb.append("\""+listOfStrings.get(i)+"\"");
        sb.append(separator);
    }

    // last string, no separator
    sb.append(listOfStrings.get(listOfStrings.size()-1));

    return sb.toString();
}





}

What am i missing in this syntax, or is there a better way of doing this task


Solution

  • There's a couple of problems:

    1. ParseInt and ParseDouble are used for reading CSV Strings into Integer and Double respectively. See the handy table here to see what cell processors can be used for reading/writing or both. You can leave them null if you want, and Super CSV will just call toString() on each object.

    2. The exception you're getting (1 column / 8 processors) indicates that you're expecting there to be 8 columns (i.e. 8 elements in your List), but there's only 1. You're only passing a single String into Arrays.asList() - looks like you're assuming this method actually splits the String into a List (it doesn't!).

    3. Why are you converting your rent data List to a String? That is really bizarre. If your data needs any manipulation (I'm not sure if it does), then you should be updating each element in your List, not converting the whole List to a String then trying to split it up again.

    4. What is the output when you don't do any replacement, i.e. what happens when you pass your rentData list directly to listWriter.write()?

    Can I suggest you fix the processor set up (replace the ParseInt and ParseDouble with null), pass the rentData List directly to Super CSV...

    listWriter.write(rentData, processors);
    

    ...then post the result (output/stacktrace) to your question.