49

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

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

4

3 回答 3

78

使用 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 在文件中是否可用并不重要。


您还可以将 encoding 选项与其他命令一起使用:

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 }
}
于 2011-10-15T20:48:43.207 回答
12

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

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

于 2009-02-13T15:04:40.653 回答
0

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

如果文件中不仅有字节 <= 0x0F(在 BOM 之后),为了确保它是正确的 UTF-8 编码,您必须检查有效序列,并且 - 即使所有序列都有效 - 还要检查每个序列中的代码点使用可能的最短序列,并检查是否没有与高或低代理匹配的代码点。还要检查一个序列的最大字节数是否不超过 4,最高代码点是否为 0x10FFFF。最高代码点还将起始字节的有效负载位限制为不高于 0x4,并且第一个后续字节的有效负载不高于 0xF。如果所有提到的检查都成功通过,那么您的 UTF-8 BOM 说明了真相。

于 2013-06-03T15:05:20.387 回答