我有一个带有这些内容的ruby文件:
# encoding: iso-8859-1
File.open('foo.txt', "w:iso-8859-1") {|f| f << 'fòo'}
puts File.read('foo.txt').encoding
有人可以解释这里发生了什么吗?
更新
以下是我正在寻找的更好的描述:
答案 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')
。后者使字节保持不变,而前者对字符串进行转码。
更新:我会详细说明,因为我不像以前那样清晰或彻底。
如果您未使用File.read()
指定编码,则会使用Encoding.default_external
读取该文件。由于您没有自己设置,因此Ruby根据其运行环境使用值。在Windows环境中,它是IBM437;在您的Cygwin环境中,它是UTF-8。所以我的观点当然是编码是什么;它必须是,它与文件中包含的字节无关。 Ruby不会为您自动检测编码。
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,回答您的新问题:
不,# encoding: iso-8859-1
行不会更改Encoding.default_external
,它只会告诉Ruby源文件本身是用ISO-8859-1编码的。只需添加
Encoding.default_external = "iso-8859-1"
如果您希望读取的所有文件都以该编码存储。
不,我个人认为Ruby不应该自动检测编码,但合理的人可能会不同意这一点,而且“应该如此”的讨论在这里似乎是偏离主题的。
就个人而言,我使用UTF-8作为一切,在极少数情况下我无法控制编码,我在阅读文件时手动设置编码,如上所示。我的源文件始终是UTF-8。如果您正在处理无法控制且不知道编码的文件,charguess gem或类似文件将非常有用。