如何仅逐行读取 csv 文件?

问题描述 投票:0回答:1

我需要读取 csv 文件,但该文件包含断线。这是一个例子:

"name","address","link"
"7eleven","city, street, 1",https://somelink/1     \\the good line
Baby-Gym,"city, street, 2\",https://somelink/2     \\the broken line because it has \", sequence

在此示例中,CSV 文件的第二行已损坏,因为“address”的值包含

\",
序列。

我无法更改 CSV 文件。我只想阅读并忽略这些断线。但是,当 com.opencsv 库使用 csvReader.readNext() 读取超过一行(大约 5k 行)时,我遇到了意外行为。

这是我用来读取 CSV 文件的代码:

try (Reader reader = new BufferedReader(new InputStreamReader(is))) {
    CSVParser parser = new CSVParserBuilder()
            .withSeparator(',')
            .withQuoteChar('"')
            .build();
    try (CSVReader csvReader= new CSVReaderBuilder(reader)
            .withSkipLines(1)
            .withCSVParser(parser)
            .build()) {

        Set<info> infoList = new HashSet<>();
        String[] infoParts;

        while ((infoParts = csvReader.readNext()) != null) {
            // code
        }
    }
}

如何使用 OpenCSV 逐行读取,同时避免由于单条断线的存在而忽略 5k 行?

我无法在任何地方找到有关如何解决此问题的信息。 我尝试使用

new CSVReaderBuilder(reader).withMultilineLimit(1)
,但它只是抛出异常...... 我查看了 CSVParser 和 CSVReader 文档,但没有找到必要的设置。请帮助我。

java opencsv csvreader
1个回答
0
投票

执行此操作的一种方法是将文件拆分为单独的

String
并单独解析每个。这意味着为每一行创建一个新的
CSVParser
,这可能会很昂贵——我还没有对这种方法进行基准测试:

package com.example.so;

import com.opencsv.CSVParser;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvValidationException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class OpenCSVEg {
    public static void main(String[] args) throws CsvValidationException, IOException {
        String csv = "\"name\",\"address\",\"link\"\n" +
                "\"7eleven\",\"city, street, 1\",https://somelink/1\n" +
                "Baby-Gym,\"city, street, 2\\\",https://somelink/2\n" +
                "\"7eleven2\",\"city, street, 3\",https://somelink/3\n";

        try (BufferedReader reader = new BufferedReader(new StringReader(csv))) {
            List<String> csvLines = reader.lines().toList();
            List<String[]> items = csvLines.stream().skip(1).map(s -> {
                // the parser has internal state, so we need a new one for each row
                CSVParser parser = new CSVParserBuilder()
                        .withSeparator(',')
                        .withQuoteChar('"')
                        .build();
                try (CSVReader csvReader = new CSVReaderBuilder(new StringReader(s))
                        .withCSVParser(parser)
                        .build()) {

                    return Optional.of(csvReader.readNext());

                } catch (Exception e) {
                    return Optional.<String[]>empty();
                }
            }).flatMap(Optional::stream).collect(Collectors.toList());
            System.out.println(items);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.