8

我使用一个 iPhone 应用程序,它会定期通过电子邮件向我发送 CSV 格式的日志。我有一个 ruby​​ 脚本,可以将该日志中的数据与旧日志相加。最近,应用程序开发人员发布了一个更新,由于某种未知原因,在每行末尾添加了一个回车,导致我的脚本失败。根据文档,:row_end默认情况下应该是:auto,它应该接受\r\n\n(在 1.9.2 中)。我尝试使用 Ruby 1.8.7、1.9.2 和 FasterCSV 和 1.8.7。我通过这些不同的尝试收到各种错误消息,包括

  • CSV::IllegalFormatError
  • 未加引号的字段不允许\r\n(第 1 行)(FasterCSV::MalformedCSVError
  • 不能复制NilClass(TypeError)

在 1.9.2 中。(\r不在字段中,它是行尾!)数据以前看起来像这样:

03-12-2012 07:59,120.0,
03-11-2012 08:27,120.0,
03-10-2012 07:57,120.0,

现在看起来像这样:

03-12-2012 07:59,120.0,^M
03-11-2012 08:27,120.0,^M
03-10-2012 07:57,120.0,^M

考虑到 CSV 可能认为^M是在最后一个字段中,我尝试添加另一个逗号:

03-12-2012 07:59,120.0,,^M

无济于事。

我唯一能想象的是 CSV 要求所有字段都用双引号引起来?我可以想到各种解决方法,例如先读取文件,然后用 CSV 处理数组,但首先我想找出我做错了什么。似乎它应该工作。

顺便说一句,我的代码很简单:

CSV.foreach(File.join($import_dir, file)) do |record|

我试过设置:row_end => "\r\n"无济于事。

我在 Mac OS X 10.6.8 上。

4

5 回答 5

8

因为 CSV 需要在自动时读取/解析整个文件row_end,所以我需要执行以下操作以防止格式化和编码异常。

  • 通过解码文件File.read
  • 删除那些讨厌的回车(可能是一个或多个)
  • 将清理后的文件解析为 CSV
file = File.read(temp_file.path, encoding: 'ISO-8859-1:UTF-8')
file = file.tr("\r", '')

CSV.parse(file, headers: true) do |row|
  # do all the things
end

注意:我将 Ruby 2.1.3 版本用于 Rails 4 应用程序。

于 2015-02-12T05:18:32.200 回答
5

尝试设置row_end

"\r\n"

这与 '\r\n' 不同:单引号字符串只允许您转义 ' 和 \,其他任何内容都被视为文字 \,即

'\r' == "\\r"

是真的

于 2012-05-18T20:21:01.567 回答
3

你提到了尝试:row_end => '\r\n'。单引号将(大多数情况下)反斜杠视为常规反斜杠字符;试试:row_end => "\r\n",用双引号。

于 2012-05-18T20:19:33.773 回答
3

在 1.9.3 中为我工作:

mark@ubuntu:~$ irb
1.9.3p0 :001 > require 'csv'
 => true
1.9.3p0 :002 > CSV.foreach("rn.csv") do |row|
1.9.3p0 :003 >   p row
1.9.3p0 :004 > end
["1","2","3","4","5"]
["6","7","8","9","10"]

该文件确实有回车:

mark@ubuntu:~$ od -a rn.csv
0000000   1   ,   2   ,   3   ,   4   ,   5  cr  nl   6   ,   7   ,   8
0000020   ,   9   ,   1   0  cr  nl
0000027
于 2012-05-18T23:48:24.643 回答
2

文件的行实际上以 \r\r\n 结尾,而不是 \r\n 这很尴尬,我应该更详细地检查文件。我假设行尾是 \n,因为我在 Unix 机器上。但是,当 Emacs 打开文件时,它会自动进入“DOS”模式,因此它将 \r\n 显示为新行,并且仅将多余的 \r 显示为“^M”

于 2012-05-20T16:23:18.907 回答