我正在使用SuperCSV将CSV记录解析为Object。我的CSV文件最后有额外的列,我只想处理前X列。因此,我为前X列和相同大小的String[]
定义CellProcessor[]
映射。但它似乎不起作用,并抛出异常数量的单元处理器应该与列数完全相同。
如果我遗失了某些东西,有人可以告诉我。即使我不想要它们,我是否需要定义映射数组以具有与五个完全相同的列?
public CsvToBeanParser(Reader reader, Class<T> type, CsvPreference preference, CellProcessor[] cellProcessors, String[] mapping, boolean skipHeader)
throws IOException {
this.beanReader = new CsvBeanReader(reader, preference);
this.mapping = mapping;
if (skipHeader) {
beanReader.getHeader(true);
}
this.cellProcessors = cellProcessors;
this.type = type;
}
/**
* Parse and return record.
*
* @return
* @throws Exception
* if there is any parsing error
*/
public T getItem() throws Exception {
try {
return (T) beanReader.read(type, mapping, cellProcessors);
} catch (Exception e) {
LOG.error("Error parsing record", e);
throw e;
}
}
以下是我的映射和单元处理器
String[] mapping = {"column1", "column2"};
CellProcessor[] cellProcessors = {null, null};
这适用于文件
column1, column2
1,2
但失败(我想忽略column3)
column1, column2, column3
1,2,3
答案 0 :(得分:5)
如果您使用CSV文件的标题作为nameMapping
,那么您永远不需要知道有多少列,您只需使用它们即可。如果它们不适合映射(它们的名称与bean中的setter不对应),那么您需要为自己的nameMapping
提供正确数量的元素。
如果您的CSV文件有一个标题,并且您知道您只需要前两列,那么您只需提供一个与标题大小相同的nameMapping数组(以及可选的单元格处理器数组),但只提供前两个元素填充。
String[] header = beanReader.getHeader(true);
// only interested in first 2 columns (rest set to null)
String[] nameMapping =
Arrays.copyOf(new String[]{"column1","column2"}, header.length);
// processors are optional, but you can populate these if you want
CellProcessor[] processors = new CellProcessor[header.length];
// TODO: read your CSV here...
答案 1 :(得分:0)
如果您无权访问标题或解析非常大的文件,则可以执行以下操作:
只需扩展CsvBeanReader
public class FlexibleCsvBeanReader extends CsvBeanReader {
public FlexibleCsvBeanReader(final Reader reader, final CsvPreference preferences) {
super(reader, preferences);
}
@Override
protected List<Object> executeProcessors(final List<Object> processedColumns, final CellProcessor[] processors) {
// we have to make sure that processors.length is equal to columnSize (thats the real column-count of the csv)
final int columnSize = getColumns().size();
// resize the array
final CellProcessor[] newProcessors = new CellProcessor[columnSize];
System.arraycopy(processors, 0, newProcessors, 0, processors.length);
// do default stuff
return super.executeProcessors(processedColumns, newProcessors);
}
}
只要新列仅在结尾处,就可以忽略名称映射。如果您认为这是一种不好的做法,您也必须覆盖read
方法。
您还可以缓存已调整大小的阵列,因为根据您的处理器,可能需要一些时间。但是,只有在每行应用相同的CellProcessor
数组时,这才有意义。