ruby1.9错误的文件编码在Windows上

我有这些内容的ruby文件:

# encoding: iso-8859-1 File.open('foo.txt', "w:iso-8859-1") {|f| f << 'fòo'} puts File.read('foo.txt').encoding 
  • 当我从Windows命令提示符运行它ruby 1.9.3我得到:IBM437
  • 当我从cygwin ruby​​ 1.9.3运行它时,得到:UTF-8
  • 我期望得到的是:iso-8859-1

有人可以解释这里发生了什么?

UPDATE

以下是我正在寻找的更好的描述:

  • 我现在明白了,谢谢Darshan默认情况下ruby会在Encoding.default中加载文件_external,但是不应该用#encoding:iso-8859-1这行覆盖那个?
  • 应该ruby能够自动检测文件的编码? 有什么文件系统的编码是属性?
  • 什么是我最好的select“记住”我保存文件的编码?

Solutions Collecting From Web of "ruby1.9错误的文件编码在Windows上"

读取文件时没有指定编码。 除了那里,你正在非常小心的指定它,但是你用默认编码读取它。

 File.open('foo.txt', "w:iso-8859-1") {|f| f << 'fòo'.force_encoding('iso-8859-1')} File.open('foo.txt', "r:iso-8859-1") {|f| puts f.read().encoding } # => ISO-8859-1 

另外请注意,您可能的意思是'fòo'.encode('iso-8859-1')而不是'fòo'.force_encoding('iso-8859-1') 。 后者保留字节不变,而前者转码字符串。

更新:我会详细说一下,因为我没有那么清楚或彻底。

  1. 如果您没有使用File.read()指定编码, File.read()使用Encoding.default_external读取该文件。 由于您不是自己设置的,所以Ruby根据所运行的环境使用了一个值。在您的Windows环境中,它是IBM437; 在你的Cygwin环境中,它是UTF-8。 所以我上面的观点当然是编码是这样的; 它必须是,而且与文件中包含的字节无关。 Ruby不会自动检测你的编码。

  2. force_encoding()不会更改字符串中的字节,只会改变附加到这些字节的编码。 如果你告诉Ruby“假装这个字符串是ISO-8859-1”,那么当你告诉它“请把这个字符串写为ISO-8859-1”时,它不会对它们进行转码。 encode()为您转码,就像写入文件,如果你不欺骗它这样做。

把它们放在一起,如果你有ISO-8859-1的源文件:

 # encoding: iso-8859-1 # Write in ISO-8859-1 regardless of default_external File.open('foo.txt', "w:iso-8859-1") {|f| f << 'fòo'} # Read in ISO-8859-1 regardless of default_external, # transcoding if necessary to default_internal, if set File.open('foo.txt', "r:iso-8859-1") {|f| puts f.read().encoding } # => ISO-8859-1 puts File.read('foo.txt').encoding # -> Whatever is specified by default_external 

如果你有一个UTF-8的源文件:

 # encoding: utf-8 # Write in ISO-8859-1 regardless of default_external, transcoding from UTF-8 File.open('foo.txt', "w:iso-8859-1") {|f| f << 'fòo'} # Read in ISO-8859-1 regardless of default_external, # transcoding if necessary to default_internal, if set File.open('foo.txt', "r:iso-8859-1") {|f| puts f.read().encoding } # => ISO-8859-1 puts File.read('foo.txt').encoding # -> Whatever is specified by default_external 

更新2,回答你的新问题:

  1. 不, # encoding: iso-8859-1行不改变Encoding.default_external ,它只告诉Ruby源文件本身是在ISO-8859-1中编码的。 只需添加

     Encoding.default_external = "iso-8859-1" 

    如果你期望所读取的所有文件都以该编码存储。

  2. 不,我个人认为Ruby应该自动检测编码,但是合理的人可能会不同意这个观点,而关于“应该如此”的讨论似乎在这里脱节。

  3. 就个人而言,我使用UTF-8处理任何事情,在极少数情况下我无法控制编码,所以当我读取文件时手动设置编码,如上所示。 我的源文件总是UTF-8。 如果你正在处理的文件,你无法控制,不知道编码, charguess宝石或类似的将是有益的。