删除无效字节,保留有效的UTF-8

问题描述 投票:0回答:1

(我在here发布了类似的问题,但这个新问题不是重复的)。

我在这里开发的软件必须使用 Ruby 2.6.10 或 1.9.3 运行:

可重现的小问题:

b = "L\xF6sé侍"

我们这里有一个字符串,其中一个字节在 UTF-8 中是非法的(它是十六进制 F6 的字节)。从 Ruby 的角度来看,字符串的编码是

Encoding::UTF_8
。查看字节序列,我们可以看到

p b.bytes.to_a

=>

[76, 246, 115, 195, 169, 228, 190, 141]

我的目标是从字符串中删除 UTF-8 中非法的所有字节。我想在我的简单示例中获得一个内容为

"Lsé侍"
.

的字符串。

我试过了

c1 = b.encode('UTF-8', invalid: :replace, replace: '')

但是

c1
b
具有相同的内容。然后我就尝试了

b.force_encoding(Encoding::ASCII_UTF8)
c2 = b.encode('UTF-8', invalid: :replace, replace: '')

但这也会删除字符 é 和 侍,因为它们在 ASCII 中无效。

我还考虑将 UTF8 中无效的字节值放在一起硬编码列表,然后简单地从字符串中删除它们,但这很丑陋。

有什么想法可以做到这一点吗?

更新:我根据我在

irb
中的实验发布了代码,但事实证明irb在这里的行为似乎与非交互式Ruby有点不同。您可以在here找到屏幕截图,该屏幕截图基于用户@mate给出的评论。为了使其工作,我无法在 JRuby 程序中分配该字符串(这在编译时已经被拒绝),而是从文件中读取它(无论如何,这就是我们“真实”应用程序中发生的情况)。

因此,如果您想重现该示例,请从此下载链接下载包含错误文本的文件,并使用以下 Ruby 脚本来运行它:

p RUBY_VERSION
str = File.read("./errf.txt")
p str.bytes.to_a
str2 = str.encode('UTF-8', invalid: :replace, replace: '')
p str2.bytes.to_a
ruby encoding
1个回答
0
投票

您可以使用

each_char
拆分字符串,使用
valid_encoding?
选择有效字符,然后重新组合剩余的字符:

b = "L\xF6sé侍"
p b
p b.each_char.select(&:valid_encoding?).join()

输出:

"L\xF6sé侍"
"Lsé侍"
© www.soinside.com 2019 - 2024. All rights reserved.