如何在Ruby中将BOM标记写入文件

我有一些带拐杖的工作代码,可以将BOM标记添加到新文件中。

#writing File.open name, 'w', 0644 do |file| file.write "\uFEFF" file.write @data end #reading File.open name, 'r:bom|utf-8' do |file| file.read end 

有没有办法自动添加标记而不在数据之前写出神秘的"\uFEFF" ? 像File.open name, 'w:bom' # this mode has no effect可能File.open name, 'w:bom' # this mode has no effect

唉,我认为你的手动方法是要走的路,至少我不知道更好的方法:

http://blog.grayproductions.net/articles/miscellaneous_m17n_details

引用JEG2的文章:

Ruby 1.9不会自动为您的数据添加BOM,因此如果您需要,您将需要处理它。 幸运的是,它并不太难。 基本思想是打印文件开头所需的字节。

****这个答案导致一个新的gem: file_with_bom ****

我在过去遇到了类似的问题,我使用w -mode的其他编码变体扩展了File.open

 class File BOM_LIST_hex = { Encoding::UTF_8 => "\xEF\xBB\xBF", #"\uEFBBBF" Encoding::UTF_16BE => "\xFE\xFF", #"\uFEFF", Encoding::UTF_16LE => "\xFF\xFE", Encoding::UTF_32BE => "\x00\x00\xFE\xFF", Encoding::UTF_32LE => "\xFE\xFF\x00\x00", } BOM_LIST_hex.freeze def utf_bom_hex(encoding = external_encoding) BOM_LIST_hex[encoding] end class << self alias :open_old :open def open(filename, mode_string = 'r', options = {}, &block) #check for bom-flag in mode_string options[:bom] = true if mode_string.sub!(/-bom/i,'') f = open_old(filename, mode_string, options) if options[:bom] case mode_string #r|bom already standard since 1.9.2 when /\Ar/ #read mode -> remove BOM #remove BOM bom = f.read(f.utf_bom_hex.bytesize) #check, if it was really a bom if bom != f.utf_bom_hex.force_encoding(bom.encoding) f.rewind #return to position 0 if BOM was no BOM end when /\Aw/ #write mode -> attach BOM f = open_old(filename, mode_string, options) f << f.utf_bom_hex.force_encoding(f.external_encoding) end #mode_string end if block_given? yield f f.close end end end end #File 

Testcode:

 EXAMPLE_TEXT = 'some content öäü' File.open("file_utf16le.txt", "w:utf-16le|bom"){|f| f << EXAMPLE_TEXT } File.open("file_utf16le.txt", "r:utf-16le|bom:utf-8"){|f| p f.read } File.open("file_utf16le.txt", "r:utf-16le:utf-8", :bom => true ){|f| p f.read } File.open("file_utf16le.txt", "r:utf-16le:utf-8"){|f| p f.read } File.open("file_utf8.txt", "w:utf-8", :bom => true ){|f| f << EXAMPLE_TEXT } File.open("file_utf8.txt", "r:utf-8", :bom => true ){|f| p f.read } File.open("file_utf8.txt", "r:utf-8|bom", ){|f| p f.read } File.open("file_utf8.txt", "r:utf-8", ){|f| p f.read } 

一些评论:

  • 代码来自1.9倍(但它仍然有效)。
  • 我用-bom作为bom指标(ruby 1.9使用|bom

一些需要修复的更好:

  • 使用|bom而不是-bom
  • 使用标准r|bom进行阅读
  • 使它成为ruby 1.8和1.9

也许明天我会找一些时间来重构我的代码并将其作为gem提供。