有效地使用 UTF-8 编码字符串

Effectively UTF-8 encode a string

我是 运行 WSL Debian 上的一个脚本,它从本地安装的共​​享驱动器中获取 Windows 文件。问题是文件名编码错误,即使 #encoding returns #<Encoding:UTF-8>。示例:

"J\u00E9r\u00E9my".encoding  # #<Encoding:UTF-8>

\u00E9é的Unicode字符,所以我假设编码是Unicode

我已经从相关问题 (Convert a unicode string to characters in Ruby?, How to convert a string to UTF8 in Ruby) 中尝试了几种编码组合,但 none 符合我的需要。 我也尝试过不同的“魔术评论”encoding: <ENCODING>,但没有令人满意的结果。

您使用什么方法来识别和修复编码问题?


Edit1:Stefan 要求代码点:
"J\u00E9r\u00E9my".each_codepoint.to_a
# [74, 233, 114, 233, 109, 121]

Encoding.default_external

Encoding.default_external
# #<Encoding:US_ASCII>

这让我感到惊讶,因为我在文件顶部有神奇的评论 # encoding: utf-8


Edit2:明确设置 default_internaldefault_external 编码为 Encoding::UTF_8 修复了问题

# encoding: utf-8

Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8

虽然我想更进一步并真正理解为什么需要这样做

"J\u00E9r\u00E9my".encoding
#=> #<Encoding:UTF-8>
"J\u00E9r\u00E9my".each_codepoint.to_a
#=> [74, 233, 114, 233, 109, 121]

琴弦非常好。它们包含正确的字节并具有正确的编码。

它们以这种方式打印,因为您的外部编码设置为(或识别为)US-ASCII:

Encoding.default_external
#=> #<Encoding:US_ASCII>

Ruby 假定您的终端只能呈现 ASCII 字符,因此使用转义序列打印 UTF-8 字符。 (当使用 p / String#inspect 时)

外部编码通常根据您的语言环境自动确定:

$ LANG=C            ruby -e 'p Encoding.default_external'
#<Encoding:US-ASCII>

$ LANG=en_US.UTF-8  ruby -e 'p Encoding.default_external'
#<Encoding:UTF-8>

将终端或系统的编码/区域设置设置为 UTF-8 应该可以解决问题。