如何在 Ruby 中读取 ibm437 中编码的 json

How to read json encoded in ibm437 in Ruby

我有一个 json 文件,其中包含以下数据:

{"help":true}

2016 年 Windows 的平台,当我在记事本++中打开文本文件时,编码显示为 UCS-2 LE BOM,当我使用 ruby 显示编码时,它是 ibm437,当我尝试用以下内容解析 json 它的错误:

ruby/2.5.0/json/common.rb:156:in `parse': 765: unexpected token at ' ■{' (JSON::ParserError)

我的代码如下:

require 'json'
def current_options
    dest='C:/test.json'
    file = File.read(dest)
    if(File.exist?(dest)) 
      p file.encoding
      p file
      @data_hash ||= JSON.parse(file)
      return @data_hash
    else
      return {}
    end
end

p current_options

输出如下所示:

PS C:\> & "C:\ruby\bin\ruby.exe" .\ruby.rb #this is the file that contains my above code
#<Encoding:IBM437>
"\xFF\xFE{\x00\"\x00h\x00e\x00l\x00p\x00\"\x00:\x00t\x00r\x00u\x00e\x00}\x00"
Traceback (most recent call last):
        3: from ./ruby.rb:20:in `<main>'
        2: from ./ruby.rb:13:in `current_options'
        1: from C:/ruby/lib/ruby/2.5.0/json/common.rb:156:in `parse'
C:/ruby/lib/ruby/2.5.0/json/common.rb:156:in `parse': 765: unexpected token at ' ■{' (JSON::ParserError)

如果我使用 notepad++ 将编码从 UCS-2 LE BOM 更改为 utf-8,然后在我的代码中解析它,它可以正常工作,但问题是另一个应用程序管理该文件并在该文件下创建它编码格式。

PS C:\> & "C:\ruby\bin\ruby.exe" .\ruby.rb #this is the file that contains my above code
#<Encoding:IBM437>
"{\"help\":true}"
{"help"=>true}

我尝试指定编码并强制其使用 utf-8,但仍然失败:

require 'json'
def current_options
    dest='C:/test.json'
    file = File.read(dest,:external_encoding => 'ibm437',:internal_encoding => 'utf-8')
    if(File.exist?(dest)) 
      p file.encoding
      p file
      @data_hash ||= JSON.parse(file)
      return @data_hash
    else
      return {}
    end
end

p current_options

将输出:

PS C:\> & "C:\ruby\bin\ruby.exe" .\ruby.rb #this is the file that contains my above code
#<Encoding:UTF-8>
"\u00A0\u25A0{\u0000\"\u0000h\u0000e\u0000l\u0000p\u0000\"\u0000:\u0000t\u0000r\u0000u\u0000e\u0000}\u0000"
Traceback (most recent call last):
        3: from ./ruby.rb:20:in `<main>'
        2: from ./ruby.rb:13:in `current_options'
        1: from C:/ruby/lib/ruby/2.5.0/json/common.rb:156:in `parse'
C:/ruby/lib/ruby/2.5.0/json/common.rb:156:in `parse': 765: unexpected token at ' ■{' (JSON::ParserError)

我不确定如何解析这个文件,有什么建议吗? 谢谢,

\u00A0 是一个 non-breaking space。 \u25A0 是一个黑色方块。 \u0000 是一个空字节。这些不是有效的 JSON 个字符。您必须剥离或转换它们。

很可能 Ruby 猜错了编码,您的文件不是真正的 IBM437,而是真正的 UCS2-LE

你的文件确实在 UCS2-LE 中,有 BOM,所以 Notepad++ 告诉你的是事实。

据我所知,

Ruby 不会尝试找出编码。当你这样做时:

file = File.read(dest)
if(File.exist?(dest)) 
    p file.encoding

您看到的不是 Ruby 从文件内容推导出来的编码。相反,它是 OS 默认语言环境编码。在 Windows 的美国 OEM 安装上,默认编码是 IBM 437,这是原始的 DOS 编码。文件的实际编码无关紧要。

您应该能够通过提供 external_encoding => 'utf-16' 将文件转换为 UTF-8,因为 BOM 提供字节序信息。