windows上的ruby 1.9错误的文件编码

时间:2012-08-04 06:39:12

标签: ruby windows encoding

我有一个带有这些内容的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

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

更新

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

  • 我理解现在感谢Darshan,默认情况下ruby会加载文件 Encoding.default _external,但不应该#noding:iso-8859-1 换行?
  • ruby​​能否自动检测文件的编码?有没有 编码是属性的文件系统?
  • “记住”我保存文件的编码的最佳选择是什么? 在?

1 个答案:

答案 0 :(得分:7)

您在阅读文件时未指定编码。除了那里,你一直非常小心地指定它,但是你用默认编码读它。

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()指定编码,则会使用Encoding.default_external读取该文件。由于您没有自己设置,因此Ruby根据其运行环境使用值。在Windows环境中,它是IBM437;在您的Cygwin环境中,它是UTF-8。所以我的观点当然是编码是什么;它必须是,它与文件中包含的字节无关。 Ruby不会为您自动检测编码。

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

  3. 如果您有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 gem或类似文件将非常有用。