SuperCsvIterator


This week I created this iterator to read data from an csv file and return a list of beans. Maybe useful for other🙂

import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.Iterator;

import javax.annotation.Nullable;

import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.prefs.CsvPreference;

import com.google.common.base.Function;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Closeables;

/**
 * @author Andreas Höhmann
 */
public class SuperCsvIterator<T> extends AbstractIterator<T>
{
   public static <T> ImmutableList<T> toList(final CsvBeanReader beanReader,
                                             final Class<T> beanClass,
                                             final CellProcessor[] cellProcessors ) throws IOException  {

       return new FluentIterable<T>() {

         @Override
         public Iterator<T> iterator() {
            return new CsvIterator<T>( beanClass, beanReader, cellProcessors );
         }
       }.toList();
   }

   public static <T> ImmutableList<T> toList(final Reader reader,
                                             final Class<T> beanClass,
                                             final CsvPreference csvPreference,
                                             final CellProcessor[] cellProcessors ) throws IOException {

     final CsvBeanReader beanReader = new CsvBeanReader( reader, CsvPreference.STANDARD_PREFERENCE );
     try {
        return toList( beanReader, beanClass, cellProcessors );
     }
     finally {
       Closeables.close( beanReader, false );
     }
   }

   private static String[] trimHeaders( final String[] headers ) {
     return FluentIterable.from( Arrays.asList( headers ) ).transform( new Function<String, String>() {

         @Override
         @Nullable
         public String apply( @Nullable final String input )  {
           if ( input == null )
             return null;
           return input.trim();
         }
       } ).toArray( String.class );
   }

   private final Class<T> beanClass;
   private final CsvBeanReader beanReader;
   private final CellProcessor[] cellProcessors;
   private final String[] headers;

   public SuperCsvIterator(final Class<T> beanClass,
                      final CsvBeanReader beanReader,
                      final CellProcessor[] cellProcessors ) throws IOException {
      this.beanClass = beanClass;
      this.beanReader = beanReader;
      this.cellProcessors = Arrays.copyOf( cellProcessors, cellProcessors.length );
      this.headers = trimHeaders( beanReader.getHeader( true ) );
   }

   @Override
   protected T computeNext() 	{
     try {
       final T result = beanReader.read( beanClass, headers, cellProcessors );
       if ( result == null ) {
         return endOfData();
       }
       return result;
     }
     catch ( final IOException e ) {
        throw new RuntimeException( "Can't compute next csv bean element", e );
     }
  }
}

 

public final class FooCsvBean {

   public static final String[] HEADER = new String[] { "Name", "Age", "Bar", };
   public static final CellProcessor[] CELLPROCESSOR = new CellProcessor[] { null, // Name
                                                                             null, // Age
                                                                             null, // Bar
                                                                           };

   private String name, age, bar;

   // Setter + Getter
}

final ImmutableList<FooCsvBean> foos = SuperCsvIterator.toList(new FileReader( fooCsvFile ),
                                                        FooCsvBean.class,
                                                        CsvPreference.STANDARD_PREFERENCE,
                                                        FooCsvBean.CELLPROCESSOR );