【问题标题】:How can I read CSV with strange quoting in ruby?如何在 ruby​​ 中读取带有奇怪引用的 CSV?
【发布时间】:2017-09-14 00:28:48
【问题描述】:

我有 CSV 文件,其中包含如下行:

col1,col "two",col3

所以我得到Illegal quoting 错误并通过设置:quote_char => "\x00" 来修复它

["col1", "col\"two\"", "col3"]

但是有一行像

col1,col2,"col,3"

稍后在该文件中

["col1", "col2", "\"col", "3\""]

然后我逐行读取文件并调用 parse_csv 包裹在块中。设置:quote_char => "\""rescueCSV::MalformedCSVError 异常,并为特定行设置:quote_char => "\x00"retry

一切正常,直到我们得到线

col1,col "two","col,3"

在这种情况下,它来自异常rescues,设置:quote_char => "\x00",结果是

["col1", "col\"two\"", "\"col", "3\""]

Apple Numbers 能够绝对正确地打开该文件。

parse_csv 是否有任何设置可以在不以某种方式预处理字符串的情况下处理此问题?

UPD 我显示文件中的 CSV 行,以及 p 打印的结果(数组)。我的字符串中没有实际的\"

【问题讨论】:

    标签: ruby csv


    【解决方案1】:

    这是一个无效的 csv 文件。如果您有权访问源,您可以(要求)按如下方式生成数据:

    col1,"col ""two""","col,3"
    

    如果没有,唯一的选择就是自己解析数据:

    pseudocode:
    
    while(read_line) {
    
        bool InsideQuotes = false
        for each_char_in_line {
    
            if(char == doublequote)
                InsideQuotes = !InsideQuotes 
    
            if(char == ',' and !InsideQuotes)
                // separator found - process field
        }
    }
    

    这也将处理转义引号,例如 col1,"col ""two""","col,3"

    如果文件包含多行字段,则需要做更多的工作。

    【讨论】:

    • 很遗憾,我无法访问源代码。我认为这种逐字符处理会导致巨大的性能损失。处理大型 CSV 文件(数百万条记录)的那部分代码
    • @Yaroslav 好吧,希望该文件中没有像 ,24" monitor, 这样的字段 :)
    • @Yaroslav 关于性能:我不知道 Ruby 或它的性能,但我想如果这些行可以被视为数组,那也不会那么糟糕。 C/C++ 中的相同算法实际上比标准解析器更快。也许您可以检查 Ruby 是否支持内存映射文件,这也将消除对 readline 的需要(它将字符串复制到缓冲区中)。
    • @Yaroslav 我快速浏览了 Ruby String 类。虽然有一个 str[index] 返回一个 1 个字符的字符串,但我认为 getbyte(index) 会更快。这将返回一个整数,并且可以与 34 " 或 44 , 进行比较。例如,您可以通过计算当前代码中每一行中的逗号来进行快速性能测试。还有each_byteeach_char
    【解决方案2】:

    CSV 与其说是一个标准,不如说是一个每个人都认为他们用来正确描述其古怪格式的名称,尽管它们是 RFC standard for CSV,但这只是另一件没人关注的事情。

    因此,许多读取 CSV 的程序都非常宽容。 Ruby 的核心 CSV 库非常好,但不如其他库那样适应性强。那是因为你有 Ruby 可以让你摆脱困境,而在 Numbers 中你没有。

    尝试将\" 重写为"",这是传统的 CSV 格式,如上面链接的规范中所定义:

    CSV.parse(File.read.gsub(/\\"/, '""'))
    

    【讨论】:

    • 抱歉不准确,但我在文件和结果(数组)中显示 CSV 行,因为它是由p 打印的。我的字符串中没有实际的\"
    猜你喜欢
    • 2016-08-21
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 2017-12-12
    相关资源
    最近更新 更多