ruby - #byteslice 无法正确计算包含重音符号的字符串中的字节
问题描述
我注意到,当给定的字符串包含重音符号时,该byteslice
方法无法返回正确的字符,因为 Ruby 显然以某种奇怪的方式计算字符串中的字节数。那,或者我错过了有关如何计算字符串中的字节数的信息。
这是一个MWE:
text = "Càdiz"
puts text.byteslice(0)
puts text.byteslice(1)
puts text.byteslice(2)
puts text.byteslice(3)
puts text.byteslice(4)
我在终端得到的结果是这样的:
C
�
�
d
i
所以,当然,那个重音字母给我带来了麻烦。这是正常的吗?有没有办法总是得到一个字符串的第五个字符作为回报,使用text.byteslice(4)
或其他类似的方法?
解决方案
我注意到,当给定的字符串包含重音符号时,该
byteslice
方法无法返回正确的字符,
String#byteslice返回字节而不是字符,因此它无法返回字符这一事实应该不足为奇。
因为 Ruby 显然以某种奇怪的方式计算字符串中的字节数。
我看不出有什么奇怪的。您要求它返回第二个字节,它返回了第二个字节。UTF-8 是专门设计的,多字节序列的每个单独字节都是非法编码,所以如果你像这样分割一个字符,它不可能产生一个合法字符。
也就是说,它允许 UTF-8 流解码器自同步。
有没有办法总是得到一个字符串的第五个字符作为回报,使用
text.byteslice(4)
或其他类似的方法?
不,没有办法使用 获得第五个字符,byteslice
因为byteslice
它是字节,而不是字符。
但是,您可以String#[]
使用以下方法获取第五个字符:
text[4]
但是,您可能想要的不是第五个字符,而是第五个字素簇,您可以使用以下String#grapheme_clusters
方法做到这一点:
text.grapheme_clusters[4]
例如,让我们看看我的名字。用 Unicode 写我的名字有两种不同的方法:
- 约尔格
- J o <组合字符分音符> rg
请注意,第一个版本是四个字符长,第二个版本是五个字符长。不过,两者都有四个字素簇。但是,请注意,虽然字形相同,但字素簇却不同。
第一个版本以 ISO8859-15 编码为 4 个字节,但在 UTF-8 中需要 5 个字节,在 UTF-16 中需要 8 个字节,在 UTF-32 中需要 16 个字节。
第二个版本不能用 ISO8859-15 编码,因为 ISO8859-15 没有组合字符分词。事实上,它根本没有组合字符。用 UTF-8 编码第二个版本需要 6 个字节,UTF-16 10 个字节,UTF-32 20 个字节。
让我们假设第二个例子,假设它是用 UTF-8 编码的。该字符串由以下字符组成:
- U+004A 拉丁文大写字母 J
- U+006F 拉丁文小写字母 o
- U+0308 组合字符分音
- U+0072 拉丁文小写字母 r
- U+0067 拉丁文小写字母 g
这些被编码成 UTF-8 到这个字节序列中:
0x4A
0x6F
0xCC
0x88
0x72
0x67
因此,例如,如果您要请求第三个字节,您会得到0xCC
. 如果您尝试将其显示为字符串,它将失败,因为0xCC
它本身不是合法的 UTF-8 编码。它是多字节序列的第一个字节。
如果你要第三个字符,你会得到 U+0308 Combining Character Diaeresis。如果您尝试将其显示为字符串,它将失败,因为没有基本字符的组合字符没有意义。
如果你要第三个字素簇,你会得到'r'
,这可能是你想要的。
所以,简而言之:你没有得到你想要的字符的原因是你没有要求一个字符,你要求一个字节。如果你想要一个角色,你需要一个角色。但是,您可能想要的是字素簇,而不是字符。
事实上,字素簇几乎总是你想要的。
推荐阅读
- android - 如何在现有主题中扩展 API 依赖主题条目?
- python - Beutifulsoup 有时打印 None 有时
- c++ - 使用 QPainter 在 QImage 上绘图
- json - 列出 GitHub 存储库名称
- excel - 无法理解复杂的 VLookup 函数
- python - 张量和权重变化维度的总和
- amazon-web-services - 有没有一种无服务器方式可以将 MSK Kafka 主题内容消费到 S3 存储桶中?
- angular6 - 刷新页面刷新后复选框应保持选中状态
- rest-assured - 放心:我们如何使用 Hemcrest 匹配器将 Json 数组中的每个元素与 Java 中的一个特定相同值进行比较,而不是使用 Foreach 循环
- azure - Azure webapps 和 functionapps 部署随机失败