【问题标题】:How best to deal with a csv file which contains both DOS and unix line encodings如何最好地处理包含 DOS 和 unix 行编码的 csv 文件
【发布时间】:2020-08-14 23:57:38
【问题描述】:

使用 ruby​​ 2.7。

解析csv文件时,如果该文件是在unix-ish机器上创建的,然后在windows机器上编辑,我们可以得到一个文件,其中第1行以\n终止,第2行为空白并以\r\n,第 3 行也以 \n 结束。这导致CSV::MalformedCSVError (New line must be <"\n"> not <"\r"> in line 2.) 输入字符串是UTF-8 编码的。

我没有发现 CSV 类有任何运气,所以我想出的 2 个选项是解析 csv 的每一行,这将是一个很大的重写,或者使用类似 @987654325 的东西“修复”输入流@。

当输入是 UTF-8 时,下面的 gsub() 是多么疯狂。有没有更好的方法来处理错误?

irb(main):001:0> require 'csv'
=> false
irb(main):002:0> csv="name,value\n\r\nid,1"
irb(main):003:0> CSV::parse(csv)
Traceback (most recent call last):
       16: from /usr/local/bin/irb:23:in `<top (required)>'
       15: from /usr/local/bin/irb:23:in `load'
       14: from /usr/local/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
       13: from (irb):3
       12: from /usr/local/lib/ruby/2.7.0/csv.rb:686:in `parse'
       11: from /usr/local/lib/ruby/2.7.0/csv.rb:1289:in `read'
       10: from /usr/local/lib/ruby/2.7.0/csv.rb:1289:in `to_a'
        9: from /usr/local/lib/ruby/2.7.0/csv.rb:1280:in `each'
        8: from /usr/local/lib/ruby/2.7.0/csv.rb:1280:in `each'
        7: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:336:in `parse'
        6: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:823:in `parse_quotable_loose'
        5: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:49:in `each_line'
        4: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:49:in `each_line'
        3: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:52:in `block in each_line'
        2: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:842:in `block in parse_quotable_loose'
        1: from /usr/local/lib/ruby/2.7.0/csv/parser.rb:928:in `parse_quotable_robust'
CSV::MalformedCSVError (New line must be <"\n"> not <"\r"> in line 2.)
irb(main):004:0> CSV::parse(csv.gsub(/\r\n/, "\n"))
=> [["name", "value"], [], ["id", "1"]]

【问题讨论】:

    标签: ruby csv


    【解决方案1】:

    在使用 Ruby 解析文件之前,使用文件上的dos2unix 实用程序将所有行结尾转换为\n。

    【讨论】:

    • ...或File.write(outfile_name, File.read(infile_name).gsub(/\r/, ''))?
    【解决方案2】:

    字符串类似乎有一个辅助函数String#encode。

    irb(main):013:0> csv="name,value\n\r\nid,1"
    irb(main):014:0> csv.encode(universal_newline: true)
    => "name,value\n\nid,1"
    irb(main):015:0> CSV::parse(csv.encode(universal_newline: true))
    => [["name", "value"], [], ["id", "1"]]
    irb(main):016:0> csv="name,value\n\r\nid,1\r\n\n\nfoo,bar\n\r\n\r\nwibble,42"
    irb(main):017:0> CSV::parse(csv.encode(universal_newline: true))
    => [["name", "value"], [], ["id", "1"], [], [], ["foo", "bar"], [], [], ["wibble", "42"]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2022-11-25
      • 2010-10-12
      相关资源
      最近更新 更多