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

How to read json encoded in ibm437 in Ruby

提问人:Miguel Rivera 提问时间:3/19/2022 更新时间:3/21/2022 访问量:92

问:

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

{"help":true}

平台 在 Windows 2016 中,当我在记事本 ++ 中打开文本文件时,编码显示为 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)

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

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)

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

json ruby 解析 UTF-8 UCS2

评论


答:

0赞 Schwern 3/19/2022 #1

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

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

评论

0赞 Miguel Rivera 3/21/2022
谢谢 Schwern,你说得对,ruby 认为的编码是错误的,在 rici 的帮助下,我能够正确阅读它
0赞 rici 3/20/2022 #2

您的文件确实在带有 BOM 的 UCS2-LE 中,因此 Notepad++ 告诉您真相。

据我所知,Ruby 并没有试图弄清楚编码。执行此操作时:

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

你看到的不是 Ruby 从文件内容中推断出的编码。相反,它是操作系统默认区域设置编码。在美国 OEM 安装的 Windows 上,默认编码是 IBM 437,这是原始的 DOS 编码。文件的实际编码无关紧要。

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

评论

0赞 Miguel Rivera 3/21/2022
谢谢rici!我刚刚将其更改为 utf-16,它现在可以正确读取它:)