当前位置: 首页 > 面试题库 >

Univocity-如何使用迭代器样式每行返回一个bean?

夏侯兴学
2023-03-14
问题内容

介绍

我正在建立一个合并一些大的csv文件的过程。我目前正在研究使用Univocity进行此操作。我设置合并的方法是使用实​​现可比接口的bean。

给定

简化的文件如下所示:

id,data
1,aa
2,bb
3,cc

Bean看起来像这样(省略了getter和setter的方法):

public class Address implements Comparable<Address> {

    @Parsed
    private int id;
    @Parsed
    private String data;

    @Override
    public int compareTo(Address o) {
        return Integer.compare(this.getId(), o.getId());
    }
}

比较器如下所示:

public class AddressComparator implements Comparator<Address>{

    @Override
    public int compare(Address a, Address b) {
        if (a == null)
            throw new IllegalArgumentException("argument object a cannot be null");
        if (b == null)
            throw new IllegalArgumentException("argument object b cannot be null");
        return Integer.compare(a.getId(), b.getId());
    }
}

由于我不想读取内存中的所有数据,因此我想读取每个文件的最高记录并执行一些比较逻辑。这是我的简化示例:

public class App {

    private static final String INPUT_1 = "src/test/input/address1.csv";
    private static final String INPUT_2 = "src/test/input/address2.csv";
    private static final String INPUT_3 = "src/test/input/address3.csv";

    public static void main(String[] args) throws FileNotFoundException {       
        BeanListProcessor<Address> rowProcessor = new BeanListProcessor<Address>(Address.class);
        CsvParserSettings parserSettings = new CsvParserSettings();
        parserSettings.setRowProcessor(rowProcessor);       
        parserSettings.setHeaderExtractionEnabled(true);
        CsvParser parser = new CsvParser(parserSettings);

        List<FileReader> readers = new ArrayList<>();
        readers.add(new FileReader(new File(INPUT_1)));
        readers.add(new FileReader(new File(INPUT_2)));
        readers.add(new FileReader(new File(INPUT_3)));

        // This parses all rows, but I am only interested in getting 1 row as a bean.
        for (FileReader fileReader : readers) {
            parser.parse(fileReader);
            List<Address> beans = rowProcessor.getBeans();
            for (Address address : beans) {
                System.out.println(address.toString());
            }           
        }

        // want to have a map with the reader and the first bean object
        // Map<FileReader, Address> topRecordofReader = new HashMap<>();
        Map<FileReader, String[]> topRecordofReader = new HashMap<>();
        for (FileReader reader : readers) {
            parser.beginParsing(reader);
            String[] row;
            while ((row = parser.parseNext()) != null) {
               System.out.println(row[0]); 
               System.out.println(row[1]); 
               topRecordofReader.put(reader, row);
               // all done, only want to get first row
               break;        
            }
        }       
    }   
}

给出上面的示例,我该如何解析以使其遍历每行并每行返回一个bean,而不是解析整个文件?

我正在寻找这样的东西(这个不起作用的代码只是表明我正在寻找的解决方案的类型):

for (FileReader fileReader : readers) {
            parser.beginParsing(fileReader);            
            Address bean = null;
            while (bean = parser.parseNextRecord() != null) {
                topRecordofReader.put(fileReader, bean);
            }                       
        }

问题答案:

有两种方法可以迭代读取而不是将所有内容加载到内存中,第一种是使用a BeanProcessor而不是BeanListProcessor

settings.setRowProcessor(new BeanProcessor<Address>(Address.class) {
        @Override
        public void beanProcessed(Address address, ParsingContext context) {
            // your code to process the each parsed object here!
        }

为了在没有回调的情况下迭代地读取bean(并执行一些其他常见过程),我们创建了一个CsvRoutines类(从AbstractRoutines扩展-
这里有更多示例):

    File input = new File("/path/to/your.csv")

    CsvParserSettings parserSettings = new CsvParserSettings();
    //...configure the parser

    // You can also use TSV and Fixed-width routines
    CsvRoutines routines = new CsvRoutines(parserSettings); 
    for (Address address : routines.iterate(Address.class, input, "UTF-8")) {
        //process your bean
    }

希望这可以帮助!



 类似资料:
  • 在spark中使用mapPartitionsToPair/PairFlatMapFunction时,我在Internet上找到了一个类似的例子 但当康普利 我找到了的声明 所以调用应该是返回一个迭代器。 因此,有人能帮助我如何返回在javaRDD api火花迭代器?谢谢 PS:我试过下面这样的代码,但在集群上不起作用:

  • 我有一个返回: 然后另一个用户这样使用它: 如何处理任何迭代中的失败情况? 我知道我可以使用,在这种情况下,错误结果将被忽略: 的迭代器根据成功状态具有0或1项,如果为0,将过滤掉它。 但是,我不想忽略错误,而是想让整个代码块停止并返回一个新错误(基于映射中出现的错误,或者只是转发现有错误)。 在Rust中如何最好地处理此问题?

  • 我想在HashMap中搜索重复项。目前这是我的HashMap:

  • 我有一个名为计算的方法,它需要太长时间才能完成。所以我决定将我的信息列表对象部分发送到这个方法。我如何遍历每n个元素?

  • 在成批转换列表时,yield return跳过已签入if条件但由于大小限制而未添加到bucket的对象。 消息总计数:4 第一个存储区计数:2 第二个存储区计数:1 跳过消息列表中的第三条消息 在这里,我正在创建大小为250kb的存储桶。是否有其他方法保存正确的状态,或者是否需要使用for循环?

  • 将这些视为对象: 查看java文档,对于LinkedList类,LinkedList类中没有迭代器方法的实现,但是,实现是在AbstractSequentialList类中。 listIterator()方法在AbstractList类中实现,AbstractSequentialList的父类,总结一下,如果我没弄错的话,它返回一个不使用节点概念的迭代器对象。 但是方法是在LinkedList类中