【问题标题】:Effectively UTF-8 encode a string有效地 UTF-8 编码一个字符串
【发布时间】:2021-03-13 11:38:25
【问题描述】:

我正在 WSL Debian 上运行一个脚本,该脚本从本地安装的共​​享驱动器中获取 Windows 文件。问题是文件名编码错误,即使#encoding 返回#<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)中尝试了几种编码组合,但都不符合我的需求。 我也尝试了不同的“魔法 cmets”encoding: &lt;ENCODING&gt;,但没有令人满意的结果。

您识别和修复编码问题的方法是什么?


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

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

【问题讨论】:

  • 你能显示字符串的codepoints吗? Encoding.default_external 返回什么?
  • 编码注释in the file设置编码in the file。它不会更改 Windows 文件系统的编码。它怎么会这样做?
  • # encoding: utf-8 只是关于文件的编码,它仅(甚至不总是)由您的编辑器使用。编译器可能会使用它,但仅用于第一阶段:读取文件)

标签: ruby encoding utf-8


【解决方案1】:
"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 应该可以解决问题。

【讨论】:

  • 对于未来的访问者:请注意,String#codepointsstr.each_codepoint.to_a 的简写。无论哪种方式,结果都是一样的。
  • 确实,它来自我的终端设置。尽管 WSL 的终端说它使用 UTF-8,但从另一个终端运行脚本会正确打印重音字符。我会调查 WSL 设置,感谢您指引我正确的方向!
猜你喜欢
  • 2011-07-09
  • 2014-06-09
  • 2013-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多