I’m using UNIVOCITY-PARSERS for converting csv file rows into java objects.
while processing the file, if it encounters any problem any of the column in row, then it parsing getting stopped in that row and throwing exception. But i need something which will continue till end of the file just by skipping the row which has error. But i didn’t any utility classes in the api.
MY Bean class
public class ItemcodeBean { @Trim @NullString(nulls = { " ", "" }) @Parsed(field = "ItemCode") private String itemCode; @Trim @NullString(nulls = { " ", "" }) @Parsed(field = "PartNumber") private String partNumber; @Trim @NullString(nulls = { " ", "" }) @Parsed(field = "ModelNumber") private String modelNumber; }
My Main Class
public class TestClass { private BeanListProcessor<ItemcodeBean> rowProcessor = null; private CsvParser parser = null; public static void main(String[] args) { TestClass testClass = new TestClass(); testClass.init(); try{ ItemcodeBean itemcodeBean; while ((itemcodeBean = testClass.getRowData()) != null){ System.out.println(itemcodeBean.toString()); } }catch (Throwable ex){ System.out.println(ex.getLocalizedMessage()); } } private BeanListProcessor<ItemcodeBean> init() { // BeanListProcessor converts each parsed row to an instance of a given class, then stores each instance into a list. this.rowProcessor = new BeanListProcessor<ItemcodeBean>(ItemcodeBean.class); CsvParserSettings parserSettings = new CsvParserSettings(); parserSettings.setProcessor(rowProcessor); parserSettings.setHeaderExtractionEnabled(true); // skip leading whitespaces parserSettings.setIgnoreLeadingWhitespaces(true); //skip trailing whitespaces parserSettings.setIgnoreTrailingWhitespaces(true); //skip empty lines parserSettings.setSkipEmptyLines(true); File file = new File("C:\Users\abhishyam.c\Downloads\Itemcode_Template.csv"); this.parser = new CsvParser(parserSettings); //parser.parse(file); parser.beginParsing(file); return rowProcessor; } private ItemcodeBean getRowData() throws Throwable { String[] row; try { while ((row = parser.parseNext()) != null){ return rowProcessor.createBean(row, parser.getContext()); } }catch (DataProcessingException e){ throw new DataProcessingException(e.getColumnName(),e); } // parser.stopParsing(); return null; } }
Advertisement
Answer
Just use an error handler and it will keep going unless you throw the exception yourself:
//Let's set a RowProcessorErrorHandler to log the error. The parser will keep running. settings.setProcessorErrorHandler(new RowProcessorErrorHandler() { @Override public void handleError(DataProcessingException error, Object[] inputRow, ParsingContext context) { println(out, "Error processing row: " + Arrays.toString(inputRow)); println(out, "Error details: column '" + error.getColumnName() + "' (index " + error.getColumnIndex() + ") has value '" + inputRow[error.getColumnIndex()] + "'"); } });
UPDATE: You can prevent the row to be discarded by using a RetryableErrorHandler instead. This is a special implementation added to version 2.3.0, and allows the user to call the methods setDefaultValue()
to assign a value to the problematic column, and keepRecord
to prevent the record from being discarded.
Example:
settings.setProcessorErrorHandler(new RetryableErrorHandler<ParsingContext>() { @Override public void handleError(DataProcessingException error, Object[] inputRow, ParsingContext context) { //if there's an error in the first column, assign 50 and proceed with the record. if (error.getColumnIndex() == 0) { setDefaultValue(50); } else { //else keep the record anyway. Null will be used instead. keepRecord(); } } });
Note that if error.getColumnIndex()
returns -1, there’s nothing that can be done to save the record, and it will be skipped regardless. You can use this to log the error details.