【问题标题】:Ignore extra columns in csv - SuperCSV忽略 csv 中的额外列 - SuperCSV
【发布时间】:2013-06-10 14:00:12
【问题描述】:

我正在使用 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

【问题讨论】:

  • 你能不能发一些代码给我们看看?
  • 另外,您使用的是AbstractCsvReader吗?
  • 我正在使用 CsvBeanReader

标签: java supercsv


【解决方案1】:

如果您无权访问标头或无法解析非常大的文件,您可以执行以下操作:

只需扩展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 数组时才有意义。

【讨论】:

    【解决方案2】:

    如果您将 CSV 文件的标题用作nameMapping,那么您永远不需要知道有多少列,您只需使用它们即可。如果它们不适合映射(它们的名称与 bean 中的设置器不对应),那么您需要为自己的 nameMapping 提供正确数量的元素。

    如果您的 CSV 文件有一个标题,并且您知道您只需要前 2 列,那么您可以简单地提供一个与标题相同大小的 nameMapping 数组(以及可选的单元处理器数组),但只​​有填充前 2 个元素。

    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...
    

    【讨论】:

    • 谢谢,我一定会试试的。我可以将我的文件更改为具有标题。很好奇,如果我的文件没有标题怎么办?
    • 您可以读取文件两次(第一次只是读取第一行以查看有多少列,第二次读取整个文件)。
    猜你喜欢
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多