改变字符编码

时间:2011-12-22 21:48:19

标签: ruby character-encoding

我在Ruby 1.9.2p290中更改文本文件的编码时遇到问题。我在UTF-8(ArgumentError) 中收到错误 无效字节序列。问题(我认为)在于charset似乎未知。

如果我执行以下操作,请从命令行:

$ file test.txt

我明白了:

Non-ISO extended-ASCII English text, with CRLF line terminators

或者,如果我这样做:

$ file -i test.txt 

我明白了:

test.txt: text/plain; charset=unknown

然而,在Ruby中,如果我这样做:

data = File.open("test.txt").read

puts data.encoding.name

puts data.valid_encoding?

我明白了:

UTF-8
false

以下是我的代码的简化代码段:

data = File.open("test.txt").read

data.encode!("UTF-8")

data.each_line do |line|

  newfile_data << line

end

2 个答案:

答案 0 :(得分:9)

在ruby 1.9中,每个流都有2个与之关联的编码 - 外部和内部编码。 外部编码是您从流中读取的文本的编码(在您的情况下,这是文件的编码)。内部编码是从文件读取的文本的所需编码。

如果没有为流设置外部/内部编码,则将使用该进程的默认外部/内部编码。如果未指定内部编码,则使用外部编码标记(不转换)从流中读取的字符串(与String.force_encoding相同。

很可能你有

Encoding::default_external # => Encoding:UTF-8
Encoding::default_internal # => nil

并且您的文件使用基于ASCII的标准字符编码进行编码,而不是UTF-8。 您的Ruby代码从外部源读取字节序列到UTF-8字符串。由于您的字符串包含Non-ISO extended-ASCII English text,因此您获得data.valid_encoding? # => false

您需要将流的外部编码设置为文件的编码。例如,如果您使用文本файл cp 1251 编码文件,那么您需要使用以下代码阅读它:

data = File.open("test.txt", 'r:windows-1251').read    
puts data.encoding.name    # => windows-1251
puts data.valid_encoding?  # => true

甚至指定内部和外部编码:

data = File.open("test.txt", 'r:windows-1251:utf-8').read    
puts data.encoding.name    # => utf-8
puts data.valid_encoding?  # => true

答案 1 :(得分:3)

data = IO.read("test.txt", :encoding => 'windows-1252')
data = data.encode("UTF-8").gsub("\r\n", "\n")