i working on csv parser requirement , using supercsv parser library. csv file can have 25 columns(separated tab(|)) , 100k rows additional header row.
i ignore white-space lines , lines containing less 25 columns.
i using icvbeanreader name mappings(to set csv values pojo) , field processors(to handle validations) reading file.
i assuming supercsv icvbeanreader skip white space lines default. how handle if row contains less 25 column numbers?
you can writing own tokenizer.
for example, following tokenizer have same behaviour default one, skip on lines don't have correct number of columns.
public class skipbadcolumncounttokenizer extends tokenizer { private final int expectedcolumns; private final list<integer> ignoredlines = new arraylist<>(); public skipbadcolumncounttokenizer(reader reader, csvpreference preferences, int expectedcolumns) { super(reader, preferences); this.expectedcolumns = expectedcolumns; } @override public boolean readcolumns(list<string> columns) throws ioexception { boolean moreinputexists; while ((moreinputexists = super.readcolumns(columns)) && columns.size() != this.expectedcolumns){ system.out.println(string.format("ignoring line %s %d columns: %s", getlinenumber(), columns.size(), getuntokenizedrow())); ignoredlines.add(getlinenumber()); } return moreinputexists; } public list<integer> getignoredlines(){ return this.ignoredlines; } }
and simple test using tokenizer...
@test public void testinvalidrows() throws ioexception { string input = "column1,column2,column3\n" + "has,three,columns\n" + "only,two\n" + "one\n" + "three,columns,again\n" + "one,too,many,columns"; csvpreference preference = csvpreference.excel_preference; int expectedcolumns = 3; skipbadcolumncounttokenizer tokenizer = new skipbadcolumncounttokenizer( new stringreader(input), preference, expectedcolumns); try (icsvbeanreader beanreader = new csvbeanreader(tokenizer, preference)) { string[] header = beanreader.getheader(true); testbean bean; while ((bean = beanreader.read(testbean.class, header)) != null){ system.out.println(bean); } system.out.println(string.format("ignored lines: %s", tokenizer.getignoredlines())); } }
prints following output (notice how it's skipped of invalid rows):
testbean{column1='has', column2='three', column3='columns'} ignoring line 3 2 columns: only,two ignoring line 4 1 columns: 1 testbean{column1='three', column2='columns', column3='again'} ignoring line 6 4 columns: one,too,many,columns ignored lines: [3, 4, 6]
Comments
Post a Comment