java - 如何以对未闭合的双引号字符具有鲁棒性的方式解析大型 CSV 文件?

标签 java parsing csv

我正在尝试解析大型 CSV 文件(这里的大型意味着 CSV 文件通常比主内存大)。我将 CSV 逐行处理为流,这使我能够处理那些大文件。

The RFC on CSV files定义双引号字符以将后面的所有内容视为单个字段(从而转义定界符):

  1. Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes. For example:

    "aaa","b CRLF bb","ccc" CRLF zzz,yyy,xxx

有时,我的应用程序需要处理不正确的 CSV 文件,这些文件包含未闭合的双引号字符。这导致 CSV 解析器尝试将文件的整个部分从这个双引号字符开始读取到一个文件中,因为我的文件可能很大,这可能会导致内存问题。

我想做的是通过以某种方式检测此类问题并在这些情况下中止解析,使我的解析解决方案对此类情况具有鲁棒性。可能有帮助的一件事是我知道我的字段的典型长度,因此我可以对字段长度设置上限。

有谁知道一种解析 CSV 文件的方法,该方法对可能包含未闭合的双引号字符的大文件具有鲁棒性,这样它会在可能的情况下解析文件并在未闭合时先消耗所有可用内存而中止双引号存在吗?我当前的解析解决方案使用 OpenCSV,但如果这有助于解决问题,我不会有任何问题。

最佳答案

uniVocity-parsers 中使用 CSV 解析器.它甚至可以解析断引号转义。试试这个例子:

import java.io.*;
import java.util.*;

import com.univocity.parsers.csv.*;

public class Test {

    public static void main(String ... args){
        CsvParserSettings settings = new CsvParserSettings();
        settings.getFormat().setLineSeparator("\r\n");
        settings.setParseUnescapedQuotes(true); // THIS IS IMPORTANT FOR YOU
        CsvParser parser = new CsvParser(settings);

        String line1 = "something,\"a quoted value \"with unescaped quotes\" can be parsed\", something\r\n";
        System.out.println("Input line: " + line1);

        String line2 = "\"after the newline \r\n you will find \" more stuff\r\n";
        System.out.println("Input line: " + line2);

        List<String[]> allLines = parser.parseAll(new StringReader(line1 + line2));


        int count = 0;
        for(String[] line : allLines){
            System.out.println("Line " + ++count);
            for(String element : line){
                System.out.println("\t" + element);

            }
            System.out.println();
        }
    }
}

这将产生:

Input line: something,"a quoted value "with unescaped quotes" can be parsed", something

Input line: "after the newline 
 you will find " more stuff

Line 1
    something
    a quoted value "with unescaped quotes" can be parsed
    something

Line 2
    after the newline 
 you will find " more stuff

请注意,在第 2 行中,您得到了一 strip 有引号字符的多行记录。在这种情况下,解析器假定这是值的一部分,因为您正在解析未转义的引号并且输入已损坏。

现在,如果您更改此行以禁止使用断引号:

settings.setParseUnescapedQuotes(false);

您将获得:

Exception in thread "main" com.univocity.parsers.common.TextParsingException: com.univocity.parsers.common.TextParsingException - Unescaped quote character '"' inside quoted value of CSV field. To allow unescaped quotes, set 'parseUnescapedQuotes' to 'true' in the CSV parser settings. Cannot parse CSV input.
Internal state when error was thrown: line=0, charIndex=29, content parsed=a quoted value 

披露:我是这个图书馆的作者。它是开源且免费的(Apache V2.0 许可)。

关于java - 如何以对未闭合的双引号字符具有鲁棒性的方式解析大型 CSV 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30322145/

相关文章:

javascript - 解析jquery中的字符串数组

Python - 嵌套字典。错误在哪里?

用于计算导数和积分的java库

javascript - 从父标签中获取孤立文本,并分 ionic 元素

python - 如何使用 python 从内联样式标记中删除特定值对?

ruby - 如何重新排列 csv 文件中列的顺序?

python - 使用 TCP/IP block 从 Raspberry pi 读取数据

java - 如何在 Spring MVC Controller 中将表单数据作为 map 获取?

java - 如何停止数组输入限制然后结果显示输出?

java - 数据库驱动程序需要支持分布式事务还是数据库本身需要支持?