如何在Ruby中将一个字符串从windows-1252转换为utf-8?

10

我正在使用 Ruby 1.8.6 在 Windows XP 上迁移一些 MS Access 2003 数据到 MySQL 5.0(编写一个 Rake 任务来完成此操作)。

结果发现 Windows 字符串数据被编码为 windows-1252,而 Rails 和 MySQL 都假定输入为 utf-8,因此一些字符(例如撇号)可能会损坏。它们最终会变成带重音符号的 "a" 等等。

是否有人知道一种工具、库、系统、方法、仪式、咒语或咒语可以将 windows-1252 字符串转换为 utf-8?


1
当你说“我正在将一些数据从MS Access 2003迁移到MySQL 5.0”时,你的意思是“我正在将一些数据从MS Jet 4迁移到MySQL 5.0”。这个区别非常重要--你根本没有使用Access,只是Jet数据库引擎。 - David-W-Fenton
5个回答

10

对于 Ruby 1.8.6 版本,您可以使用 Ruby Iconv,它是标准库的一部分:

Iconv 文档

根据这篇有用的文章,似乎您可以像下面这样从字符串中清除不必要的 win-1252 字符:

ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
valid_string = ic.iconv(untrusted_string + ' ')[0..-2]

那么,人们可以尝试像这样进行完整的转换:

ic = Iconv.new('UTF-8', 'WINDOWS-1252')
valid_string = ic.iconv(untrusted_string + ' ')[0..-2]

9

如果您使用的是 Ruby 1.9 版本...

string_in_windows_1252 = database.get(...)
# => "Fåbulous"

string_in_windows_1252.encoding
# => "windows-1252"

string_in_utf_8 = string_in_windows_1252.encode('UTF-8')
# => "Fabulous"

string_in_utf_8.encoding
# => 'UTF-8'

谢谢,这很有用。但是我现在正在处理Ruby 1.8.6版本。我猜我可以安装1.9、RubyGems等。 - Ethan
3
我希望 Ruby 不会将 "Fåbulous" 编码成 "Fabulous",因为对于任何使用该字符的语言而言,'å' 与 'a' 是非常不同的字符。如果以 UTF-8 编码的字符串在 Windows 1252 码页中打印,则该字符串应该看起来类似于 "FÃ¥bulous",如果在 UTF-8 中打印,则应该是 "Fåbulous"。 - Andreas Magnusson

3

你好,

我也曾遇到过同样的问题。

以下这些提示可以帮助你解决问题:

始终检查正确的编码名称,以便正确地输入转换工具。如果不确定,可以使用以下命令获取iconv或recode支持的编码列表:

$ recode -l

或者

$ iconv -l

始终从原始文件开始,并对样本进行编码以便处理:
$ recode windows-1252..u8 < original.txt > sample_utf8.txt

或者

$ iconv -f windows-1252 -t utf8 original.txt -o sample_utf8.txt

安装Ruby1.9,这将大大帮助您处理编码相关的问题。即使您不在程序中使用它,您也可以始终启动一个irb1.9会话并检查字符串以查看输出结果。 Ruby 1.9中的File.open有一个新的“mode”参数,请使用它! 这篇文章非常有帮助:http://blog.nuclearsquid.com/writings/ruby-1-9-encodings
File.open('original.txt', 'r:windows-1252:utf-8')
# This opens a file specifying all encoding options. r:windows-1252 means read it as windows-1252. :utf-8 means treat it as utf-8 internally.

玩得开心,但不要说脏话!


2

如果你不是在使用Ruby 1.9,并且假设 yhager 的命令有效,那么你可以尝试以下操作:

File.open('/tmp/w1252', 'w') do |file|
  my_windows_1252_string.each_byte do |byte|
    file << byte
  end
end

`iconv -f windows-1252 -t utf-8 /tmp/w1252 > /tmp/utf8`

my_utf_8_string = File.read('/tmp/utf8')

['/tmp/w1252', '/tmp/utf8'].each do |path|
  FileUtils.rm path
end

糟糕:出现了与yhager相同的问题,原因是Windows没有iconv(或者/tmp/目录)。嗯... - James A. Rosen

2
如果你想在Unix操作系统上转换名为win1252file的文件,运行以下命令:
$ iconv -f windows-1252 -t utf-8 win1252_file > utf8_file

你可能需要在Windows上使用cygwin来完成相同的操作。


谢谢,了解到这点对未来很有帮助,但是我不确定在这种情况下该怎么做,因为我正在处理Windows XP环境中的MS Access和MySQL,而不是Cygwin。 - Ethan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接