Ruby中的字符串编码

gar*_*oat 6 ruby encoding

我最近开始使用Ruby编码,并且对某些行为感到困惑.

我正在使用2.2.3p173并显示以下内容:

__ENCODING__             #=> #<Encoding:UTF-8>  Default encoding in 2.2.3

"my_string".encoding     #=> #<Encoding:UTF-8>
Object.to_s.encoding     #=> #<Encoding:US-ASCII>
Object.new.to_s.encoding #=> #<Encoding:ASCII-8BIT>
Run Code Online (Sandbox Code Playgroud)

这种编码差异的原因是什么?

Max*_*Max 5

不错的发现!

简短的回答是它完全是任意的,它取决于 Ruby 如何在内部构建返回的字符串。

有大量内部 C 函数使用 US-ASCII 编码构造空字符串或文字字符串:rb_usascii_str_new和类似的。它们经常用于通过附加较小的字符串片段来构造字符串。几乎每个to_s方法都这样做:

[].to_s.encoding
#<Encoding:US-ASCII>
{}.to_s.encoding
#<Encoding:US-ASCII>
$/.to_s.encoding
#<Encoding:US-ASCII>
1.to_s.encoding
#<Encoding:US-ASCII>
true.to_s.encoding
#<Encoding:US-ASCII>
Object.to_s.encoding
#<Encoding:US-ASCII>
Run Code Online (Sandbox Code Playgroud)

那么为什么不Object.new.to_s呢?这里的关键是每个Object#to_s的回退to_s方法,因此为了使其具有通用性但信息丰富,他们将其编码为输出对象内部指针的值。最简单的方法是使用和 说明符。但是,任何编写 Ruby包装器的人都变得懒惰,只是将编码设置为回退到. 因此,通常返回格式化字符串的任何内容都将具有以下编码:sprintf%psprintfrb_sprintfNULLASCII-8BIT

Object.new.to_s
#<Encoding:ASCII-8BIT>
nil.sort rescue $!.to_s.encoding
#<Encoding:ASCII-8BIT>
[].each.to_s.encoding
#<Encoding:ASCII-8BIT>
Run Code Online (Sandbox Code Playgroud)

至于由脚本定义的字符串,如您所料,它们将获得默认编码 UTF-8。