Ruby中的SmarterCSV和文件编码问题

时间:2015-05-06 18:57:19

标签: ruby csv encoding smartercsv

我正在使用看似具有UTF-16LE编码的文件。如果我跑

File.read(file, :encoding => 'utf-16le')

该文件的第一行是:

"<U+FEFF>=\"25/09/2013\"\t18:39:17\t=\"Unknown\"\t=\"+15168608203\"\t\"Message.\"\r\n

如果我使用类似

的内容阅读文件
csv_text = File.read(file, :encoding => 'utf-16le')

我收到错误说明

ASCII incompatible encoding needs binmode (ArgumentError)

如果我将上面的编码切换到

csv_text = File.read(file, :encoding => 'utf-8')

我将其转到代码的SmarterCSV部分,但收到错误消息

`=~': invalid byte sequence in UTF-8 (ArgumentError)

完整代码如下。如果我在Rails控制台中运行它,它可以正常工作,但如果我使用ruby test.rb运行它,它会给我第一个错误:

require 'smarter_csv'
headers = ["date_of_message", "timestamp_of_message", "sender", "phone_number", "message"]
path = '/path/'
Dir.glob("#{path}*.CSV").each do |file|
  csv_text = File.read(file, :encoding => 'utf-16le')
  File.open('/tmp/tmp_file', 'w') { |tmp_file| tmp_file.write(csv_text) }
  puts 'made it here'
  SmarterCSV.process('/tmp/tmp_file', {
    :col_sep => "\t",
    :force_simple_split => true,
    :headers_in_file => false,
    :user_provided_headers => headers
   }).each do |row|
    converted_row = {}
    converted_row[:date_of_message] = row[:date_of_message][2..-2].to_date
    converted_row[:timestamp] = row[:timestamp]
    converted_row[:sender] = row[:sender][2..-2]
    converted_row[:phone_number] = row[:phone_number][2..-2]
    converted_row[:message] = row[:message][1..-2]
    converted_row[:room] = file.gsub(path, '')
  end
end

更新 - 2015年5月15日

最终,我决定将文件字符串编码为UTF-8,而不是深入了解SmarterCSV代码。 SmarterCSV代码中的第一个问题是它不允许用户在读取文件时指定二进制模式,但是在调整源代码来处理它之后,会弹出许多与编码相关的其他问题,其中很多都是相关的处理非UTF-8编码的文件上的各种参数。它可能是最简单的方法,但在将所有内容编码为SmarterCSV之前将其编码为UTF-8解决了我的问题。

2 个答案:

答案 0 :(得分:1)

将binmode添加到File.read来电。

File.read(file, :encoding => 'utf-16le', mode: "rb")
  

“b”二进制文件模式        抑制EOL&lt; - &gt; Windows上的CRLF转换。和        除非明确指出,否则将外部编码设置为ASCII-8BIT        指定。

参考:http://ruby-doc.org/core-2.0.0/IO.html#method-c-read

现在将正确的编码传递给SmarterCSV

SmarterCSV.process('/tmp/tmp_file', {
:file_encoding => "utf-16le", ...

<强>更新

发现smartercsv不支持二进制模式。在OP尝试修改代码但没有成功之后,决定简单的解决方案是将输入转换为UTF-8 smartercsv支持的meta_id post_id meta_key meta_value 1422 73 wpcf-milk 22 1423 73 wpcf-mw -7

答案 1 :(得分:0)

不幸的是,你正在使用'平面文件'的存储方式,而字符编码将成为两端的问题(阅读或写作)。

我建议使用类似str = str.force_encoding("UTF-8")的内容,看看你是否可以使用它。