为什么部分符号(§)无法正确读取,具体取决于它的创建位置?

时间:2016-10-14 22:17:11

标签: ruby vim command-line character-encoding

我正在尝试创建一个工具来从Minecraft日志文件中抓取用户名。在这些中,有很多部分符号,因为这是游戏用于颜色格式化的内容,我想从文件的每一行中删除它们和后面的字符。但是,当我尝试使用Ruby读取文件时,我无法获得正确的字符。为了解决这个问题,我用不同的方式检查了一堆包含部分符号的文件。文件为a.logb.logc.log

  • a.logecho §创建到文件
  • b.log是由cat我自己的Minecraft日志文件创建的,然后删除了Vim中的所有其他字符
  • c.log是在记事本中创建的

当我在记事本中查看它们时,它们都显示正确:

a.log
a.log in notepad
b.log
b.log in notepad
c.log
c.log in notepad

当我在Vim中看到它们时,它是一样的:

logfiles in vim

然后,当我在Ruby中打开它们时,事情开始变得怪异。 这是我使用的代码:

a = File.open("./a.log")
aa = a.read
puts aa.encoding
puts aa.ord
puts aa

b = File.open("./b.log")
bb = b.read
puts bb.encoding
puts bb.ord
puts bb

c = File.open("./c.log")
cc = c.read
puts cc.encoding
puts cc.ord
puts cc

这是输出:

IBM437
239
§
IBM437
167
▒
IBM437
167
▒

我认为这可能只是Ruby很奇怪,直到我使用cat来显示每个文件的内容:

$ cat a.log b.log c.log
§
▒
▒

这没有任何意义,因为编码显示相同。所以我决定用十六进制查看器(HxD)打开每个文件:

a.log
a.log in hex viewer
b.log
b.log in hex viewer
c.log
c.log in hex viewer

什么!所有这些都包含相同的字符。 EF BB BF C2 a.log中唯一有效的区别是不起作用的区别。为什么这会产生影响,我该如何修复它以便它可以与Ruby的gsub一起使用?

(我尝试使用我在String.force_encodingString.encode在线找到的一些内容,但是除了开始在输出中看到度数符号之外没有任何其他内容如果你能提供一个适用于所有三种类型日志文件的例子,我将非常感激。)

编辑:我做了一些游戏,发现它是必要的C2字节。 UTF-8使用0xC2 0xA7,UTF-16使用0x00A7。我该怎么做才能正确转换(为什么记事本和Vim没有任何问题将其显示为部分符号?)

2 个答案:

答案 0 :(得分:1)

确保您的ruby源文件也是UTF-8编码的。我已经看过你用PHP描述过很多次的症状:我的源文件是ISO,用UTF-8访问xml或其他类型的数据 - 或者反过来。

如果由于某种原因你不能或不想用UTF-8编码你的ruby文件,那么你需要挖掘文件打开函数以确保他们知道他们将处理UTF-8源。

答案 1 :(得分:1)

这个问题是某些系统并不总是确定他们正在使用的编码。在这种情况下,Ruby认为输入是IBM437,但是当我们查找该代码页时,A7处的字符不是一个部分synbol。通常情况下,口译员会混淆ISO-8859-1IBM437和其他编码。 ISO-8859-1的部分符号位于A7,因此这实际上是正确的编码。 Notepad和Vim可以正确显示它的原因是他们在猜测编码方面比cat和Ruby解释器更好。

要解决此问题,只需将force_encodingISO-8859-1一起使用,然后encode!UTF-8一起使用。