【问题标题】:Is there a way to remove the BOM from a UTF-8 encoded file?有没有办法从 UTF-8 编码文件中删除 BOM?
【发布时间】:2011-06-28 01:04:38
【问题描述】:

有没有办法从 UTF-8 编码文件中删除 BOM?

我知道我所有的 JSON 文件都以 UTF-8 编码,但编辑 JSON 文件的数据输入人员将其保存为 UTF-8 和 BOM。

当我运行我的 Ruby 脚本来解析 JSON 时,它因错误而失败。 我不想手动打开超过 58 个 JSON 文件并在没有 BOM 的情况下转换为 UTF-8。

【问题讨论】:

标签: ruby byte-order-mark


【解决方案1】:

因此,解决方案是通过 gsub 对 BOM 进行搜索和替换! 我强制将字符串编码为 UTF-8,还强制将正则表达式模式编码为 UTF-8。

我通过查看http://self.d-struct.org/195/howto-remove-byte-order-mark-with-ruby-and-iconvhttp://blog.grayproductions.net/articles/ruby_19s_string 得出了一个解决方案

def read_json_file(file_name, index)
  content = ''
  file = File.open("#{file_name}\\game.json", "r") 
  content = file.read.force_encoding("UTF-8")

  content.gsub!("\xEF\xBB\xBF".force_encoding("UTF-8"), '')

  json = JSON.parse(content)

  print json
end

【讨论】:

  • 我会推荐sub!(/^\xEF\xBB\xBF/, ''),因为 BOM 只在字符串的开头出现一次。
  • 我实际上会建议 String#delete! 而不是 String#gsub!(..., '')
  • @Jan 您的建议很好,除非您的设置默认为 UTF-8,或者至少我认为这是我的问题,因为您的命令不适用于我的。只需执行 content.sub!(/^\xEF\xBB\xBF/, '') 就会出现“无效的 UTF-8 字节序列”错误。
  • @Ryan 我认为@Jan 只是意味着使用sub 而不是gsub,但不一定意味着放弃force_encoding
【解决方案2】:

使用 ruby​​ >= 1.9.2 你可以使用模式r:bom|utf-8

这应该可以(我没有结合json测试它):

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

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


Andrew 说,File#rewind 不能与 BOM 一起使用。

如果您需要倒带功能,您必须记住位置并将rewind 替换为pos=

#Prepare test file
File.open('file.txt', "w:utf-8"){|f|
  f << "\xEF\xBB\xBF" #add BOM
  f << 'some content'
}

#Read file and skip BOM if available
File.open('file.txt', "r:bom|utf-8"){|f|
  pos =f.pos
  p content = f.read  #read and write file content
  f.pos = pos   #f.rewind  goes to pos 0
  p content = f.read  #(re)read and write file content
}

【讨论】:

  • Ruby 的单行(在 STDIN 上获取文件路径):ruby -ne 'File.open($_.strip, "r:bom|utf-8") {|f| content=f.read(f.size); f.close; File.open($_.strip, "w").write(content) }
  • 所以这对我来说失败了,因为我使用了 File#rewind。至少在 ruby​​ 1.9.2 中,使用“bom|UTF-8”只会在打开文件指针时将其前移,而当您倒带时会忘记这一点。在我看来,鉴于此编码参数,open 的实现很差。
  • @AndrewSchwartz 你是对的。我通过解决您的问题扩展了我的答案。
【解决方案3】:

您也可以使用File.readCSV.read 方法指定编码,但不要指定read 模式。

File.read(path, :encoding => 'bom|utf-8')
CSV.read(path, :encoding => 'bom|utf-8')

【讨论】:

    【解决方案4】:

    如果您只读取文件一次,“bom|UTF-8”编码效果很好,但如果您调用 File#rewind 则会失败,就像我在代码中所做的那样。为了解决这个问题,我做了以下事情:

    def ignore_bom
      @file.ungetc if @file.pos==0 && @file.getc != "\xEF\xBB\xBF".force_encoding("UTF-8")
    end
    

    这似乎运作良好。不确定是否还有其他类似类型的字符需要注意,但可以轻松地将它们内置到此方法中,该方法可以在您倒带或打开时随时调用。

    【讨论】:

      【解决方案5】:

      对我有用的 utf-8 bom 字节的服务器端清理:

      csv_text.gsub!("\xEF\xBB\xBF".force_encoding(Encoding::BINARY), '')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-21
        • 2017-12-27
        • 1970-01-01
        相关资源
        最近更新 更多