【问题标题】:How to avoid tripping over UTF-8 BOM when reading files读取文件时如何避免绊倒 UTF-8 BOM
【发布时间】:2010-10-07 07:00:55
【问题描述】:

我正在使用最近添加了 Unicode BOM 标头 (U+FEFF) 的数据馈送,而我的 rake 任务现在被它搞砸了。

我可以使用file.gets[3..-1] 跳过前 3 个字节,但是有没有更优雅的方式来读取 Ruby 中的文件,可以正确处理这个问题,无论 BOM 是否存在?

【问题讨论】:

  • 那是一个 Unicode BOM 不是 UTF-8 的。
  • 谢谢,我才意识到这一点。它实际上是 3 个字节,而不是一个......我编辑了这个问题来说这么多。

标签: ruby file unicode byte-order-mark


【解决方案1】:

在 ruby​​ 1.9.2 中,您可以使用模式r:bom|utf-8

text_without_bom = nil #define the variable outside the block to keep the data
File.open('file.txt', "r:bom|utf-8"){|file|
  text_without_bom = file.read
}

text_without_bom = File.read('file.txt', encoding: 'bom|utf-8')

text_without_bom = File.read('file.txt', mode: 'r:bom|utf-8')

BOM 是否在文件中可用并不重要。


您也可以将编码选项与其他命令一起使用:

text_without_bom = File.readlines(@filename, "r:utf-8")

(你得到一个包含所有行的数组)。

或使用 CSV:

require 'csv'
CSV.open(@filename, 'r:bom|utf-8'){|csv|
  csv.each{ |row| p row }
}

【讨论】:

  • 有没有办法使用 ruby​​ 内置的 CSV 库来处理 CSV 文件?我已经尝试将:encoding => "r:bom|utf-8" 传递给 CSV 的 foreach,但它仍然会读取 BOM,就好像它是标题第一列的一部分一样。
  • 我认为这是可能的。使用CVS.read(filename, :encoding => 'utf-8'),您可以使用CSV 设置编码(或者是CSV.load?)。我认为使用 bom-logic 也可以做到这一点::encoding => 'bom|utf-8')。我无法亲自测试它 - 抱歉。
  • 以下对我有用:file = File.open(@filename, 'r:bom|utf-8')csv = CSV.new(file, faster_csv_options)csv.each do |row|...file.close
  • 你也可以使用File#open的block.version:File.open(@filename, 'r:bom|utf-8'){|file| csv = CSV.new(file, faster_csv_options) csv.each{ |row| p row } }或更短,我测试成功:CSV.open(@filename, 'r:bom|utf-8', faster_csv_options){|csv| csv.each{ |row| p row } }andCSV.read(@filename, 'r:bom|utf-8').each{|row| p row }
  • 为什么不只是text_without_bom = File.read('file.txt', mode: 'r:bom|utf-8')
【解决方案2】:

当存在 0xEF 0xBB 0xBF 的 BOM 时,我不会“相信”某些文件被编码为 UTF-8,您可能会失败。通常在检测 UTF-8 BOM 时,当然应该是真正的 UTF-8 编码文件。但是,例如,如果有人刚刚将 UTF-8 BOM 添加到 ISO 文件中,那么如果其中有高于 0x0F 的字节,您将无法对此类文件进行如此糟糕的编码。如果内部只有 0x0F 以内的字节,则可以信任该文件,因为在这种情况下,它是一个 UTF-8 兼容的 ASCII 文件,同时它也是一个有效的 UTF-8 文件。

如果文件中不只有字节

【讨论】:

    【解决方案3】:

    我不会盲目地跳过前三个字节;如果生产者停止再次添加 BOM 会怎样?您应该检查前几个字节,如果它们是 0xEF 0xBB 0xBF,请忽略它们。这就是 BOM 字符 (U+FEFF) 采用 UTF-8 的形式;我更喜欢在尝试解码流之前处理它,因为 BOM 处理从一种语言/工具/框架到另一种语言/工具/框架是如此不一致。

    事实上,这就是您应该处理 BOM 的方式。如果文件以 UTF-16 格式提供,则必须在开始解码之前检查前两个字节,以便知道将其读取为 big-endian 还是 little-endian。当然,UTF-8 BOM 与字节顺序无关,它只是为了让您知道编码是 UTF-8,以防您还不知道。

    【讨论】:

      猜你喜欢
      • 2014-03-04
      • 2011-06-21
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多