我有这些内容的ruby文件:
# encoding: iso-8859-1 File.open('foo.txt', "w:iso-8859-1") {|f| f << 'fòo'} puts File.read('foo.txt').encoding
有人可以解释这里发生了什么?
UPDATE
以下是我正在寻找的更好的描述:
读取文件时没有指定编码。 除了那里,你正在非常小心的指定它,但是你用默认编码读取它。
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()
指定编码, 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宝石或类似的将是有益的。