【问题标题】:CsvMalformedLineException: Unterminated quoted field at end of CSV lineCsvMalformedLineException:CSV 行末尾未终止的引号字段
【发布时间】:2022-12-15 15:48:56
【问题描述】:

我正在编写代码来处理 tar.gz 文件列表,其中有多个 csv 文件。我遇到了以下错误

com.opencsv.exceptions.CsvMalformedLineException: Unterminated quoted field at end of CSV line. Beginning of lost text: [,,,,,,
]
    at com.opencsv.CSVReader.primeNextRecord(CSVReader.java:245)
    at com.opencsv.CSVReader.flexibleRead(CSVReader.java:598)
    at com.opencsv.CSVReader.readNext(CSVReader.java:204)
    at uk.ac.shef.inf.analysis.Test.readAllLines(Test.java:64)
    at uk.ac.shef.inf.analysis.Test.main(Test.java:42)

导致这个问题的代码在下面的 B 行。

public class Test {
    public static void main(String[] args) {
        try {
            Path source = Paths.get("/home/xxxx/Work/data/amazon/labelled/small/Books_5.json.1.tar.gz");
            InputStream fi = Files.newInputStream(source);
            BufferedInputStream bi = new BufferedInputStream(fi);
            GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
            TarArchiveInputStream ti = new TarArchiveInputStream(gzi);
            CSVParser parser = new CSVParserBuilder().withStrictQuotes(true)
                    .withQuoteChar('"').withSeparator(',').
                    .withEscapeChar('|').           // Line A
                     build();
            BufferedReader br = null;
            ArchiveEntry entry;
            entry = ti.getNextEntry();
            while (entry != null) {
                br = new BufferedReader(new InputStreamReader(ti)); // Read directly from tarInput
                System.out.format("\n%s\t\t  > %s", new Date(), entry.getName());
                try{
                    CSVReader reader = new CSVReaderBuilder(br).withCSVParser(parser)
                            .build();
                    List<String[]> r = readAllLines(reader);
                } catch (Exception ioe){
                    ioe.printStackTrace();
                }
                System.out.println(entry.getName());
                entry=ti.getNextEntry();        // Line B
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static List<String[]> readAllLines(CSVReader reader) {
        List<String[]> out = new ArrayList<>();
        int line=0;
        try{
            String[] lineInArray = reader.readNext();

            while(lineInArray!=null) {
                //System.out.println(Arrays.asList(lineInArray));
                out.add(lineInArray);
                line++;
                lineInArray=reader.readNext();
            }
        }catch (Exception e){
            System.out.println(line);
            e.printStackTrace();
        }
        System.out.println(out.size());
        return out;
    }
}

我还在此处附上导致此问题的 csv 文件中实际行的屏幕截图,请查看第 5213 行。我还在此处包含一个测试 tar.gz 文件:https://drive.google.com/file/d/1qHfWiJItnE19-BFdbQ3s3Gek__VkoUqk/view?usp=sharing

调试时,我有一些问题。

  • 我认为问题出在数据文件(上面第 5213 行)中的 \ 字符,它是 Java 中的转义字符。我通过在上面的代码中添加行 A 来验证这个想法,并且它有效。但是,显然我不想对此进行硬编码,因为数据中可能有其他字符导致同样的问题。所以我的问题 1 是:有没有告诉 Java 忽略转义字符?类似于withEscapeChar('|') 的反义词?更新:答案是使用'\0',感谢下面的第一条评论。
  • 调试时,我注意到我的程序在遇到上述异常后立即停止处理 tar.gz 文件中的下一个 .csv 文件。为了解释我的意思,在上面链接中包含的 tar.gz 文件中,有两个 csvs:_10.csv 和 _110.csv。有问题的行在 _10.csv 中。当我的程序遇到该行时,会抛出一个异常,程序会转到下一个文件 _110.csv (entry=ti.getNextEntry();)。这个文件实际上没问题,但是应该读取下一个 csv 文件的方法 readAllLines 将在第一行立即抛出相同的异常。我认为我的代码不正确,尤其是 while 循环:我怀疑输入流仍然停留在导致异常的先前位置。但我不知道如何解决这个问题。请帮忙?

【问题讨论】:

  • 您是否尝试过 similar question 中推荐的任何其他转义字符,例如 NUL char '\0'
  • 您还必须确定数据提供者使用什么字符来转义字符串中的嵌入引号。处理 CSV 中嵌入双引号的标准方法是连续使用两个双引号字符,即"String containing "" a double quote"。这在技术上不是与 Java 反斜杠相同方式的转义字符,因为它仅适用于双引号字符,而不是一般转义。
  • 大多数推荐 RFC4180Parser 来解决转义反斜杠问题,如 DZone 中所述:OpenCSV: Properly Handling Backslashes
  • @hc_dev 我刚刚试过了,可以用,谢谢!我更新了我的帖子。仍然想知道第二个问题的答案,因为我认为我的 while 循环是错误的......
  • 看起来您没有关闭(或使用 try-with-resources for )BufferedReader 和/或其他输入流。在更改“父”资源管理器的状态之前,您可能需要在 catch 子句中对该阅读器进行一些维护 ti

标签: java opencsv


【解决方案1】:

使用 RFC4180Parser 对我有用。

【讨论】:

    猜你喜欢
    • 2011-06-25
    • 2018-12-29
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多