gpt4 book ai didi

ruby - 在 ruby​​ 中处理编码

转载 作者:太空宇宙 更新时间:2023-11-03 17:47:42 25 4
gpt4 key购买 nike

我有一个好字符串和一个坏字符串

处理我做的坏字符串

bad.encode("iso-8859-1").force_encoding("utf-8")

使其可读

如果我这样做

good.encode("iso-8859-1").force_encoding("utf-8")

我得到 Encoding::UndefinedConversionError: U+05E2 from UTF-8 to ISO-8859-1

好的和坏的字符串一开始都是 UTF-8,但是好的字符串是可读的,坏的是,好吧,坏。

我不知道如何检测字符串是否正确,我正在尝试找到一种方法来处理字符串并使其以正确的编码可读

类似的东西

if needs_fixin?(str)
str.encode("iso-8859-1").force_encoding("utf-8")
else
str
end

我唯一能想到的就是捕获异常跳过编码修复部分,但我不想代码故意有异常。

类似str.try(:encode, "iso-8859-1").force_encoding("utf-8") rescue str

错误的字符串类似于

×¢×××× ×¢×¥ ×'××¤×¡× ×פת×ר ×× ××רק××

最佳答案

我怀疑您的问题是双重编码的字符串。由于各种原因,这非常糟糕,但这里的 tl;dr 是它不能完全修复,您应该尽可能修复字符串被双重编码的根本问题。

这会产生一个带有 UTF-8 字符的双重编码字符串:

> str = "汉语 / 漢語"
=> "汉语 / 漢語"
> str.force_encoding("iso-8859-1")
=> "\xE6\xB1\x89\xE8\xAF\xAD / \xE6\xBC\xA2\xE8\xAA\x9E"
> bad = str.force_encoding("iso-8859-1").encode("utf-8")
=> "æ±\u0089语 / æ¼¢èª\u009E"

然后您可以通过将双重编码的 UTF-8 重新解释为 ISO-8859-1 然后声明编码实际上是 UTF-8 来修复它

> bad.encode("iso-8859-1").force_encoding("utf-8")
=> "汉语 / 漢語"

但是你不能将实际的 UTF-8 字符串转换成 ISO-8859-1,因为 UTF-8 中有代码点,而 ISO-8859-1 没有任何明确的编码方式

> str.encode("iso-8859-1")
Encoding::UndefinedConversionError: ""\xE6\xB1\x89"" from UTF-8 to ISO-8859-1

现在,您实际上无法一直检测并修复此问题,因为 "there's no way to tell whether the result is from incorrectly double-encoding one character, or correctly single-encoding 2 characters."

因此,您剩下的最好方法就是启发式方法。 Borshuno 的建议在这里不起作用,因为它实际上会破坏不可转换的字节:

> str.encode( "iso-8859-1", fallback: lambda{|c| c.force_encoding("utf-8")} )
.0=> " / "

如果可能的话,最好的做法是解决双重编码问题,这样它就不会发生了。下一个最佳做法是,如果您怀疑它们可能被双重编码,则将 BOM 字节添加到您的 UTF-8 字符串中,因为您随后可以检查这些字节并确定您的字符串是否已被重新编码。

> str_bom = "\xEF\xBB\xBF" + str
=> "汉语 / 漢語"
> str_bom.start_with?("\xEF\xBB\xBF")
=> true
> str_bom.force_encoding("iso-8859-1").encode("utf-8").start_with?("\xEF\xBB\xBF")
=> false

如果您可以假定 BOM 在您的“正确”字符串中,那么您可以通过检查 BOM 是否存在来检查双重编码。如果不是(即它已被重新编码),那么您可以执行解码例程:

> str_bom.force_encoding("iso-8859-1").encode("utf-8").encode("iso-8859-1").force_encoding("utf-8").start_with?("\xEF\xBB\xBF")
=> true

如果您不能确定 BOM,那么您可以通过计算不可打印的字符或超出正常预期结果集(您的string 看起来像是在处理希伯来语;例如,您可以说任何包含 >50% 非希伯来语字母的字符串都是双重编码的),因此您可以尝试对其进行解码。

最后,您将不得不退回到异常处理,并希望您知道该字符串据称被声明为双重编码时的编码:

str = "汉语 / 漢語"
begin
str.encode("iso-8859-1").encode("utf-8")
rescue Encoding::UndefinedConversionError
str
end

然而,即使你知道一个字符串是双重编码的,如果你不知道它在转换为 UTF-8 时被错误声明的编码,你就无法进行反向操作:

> bad_str = str.force_encoding("windows-1252").encode("utf-8")
=> "汉语 / 漢語"
> bad_str.encode("iso-8859-1").force_encoding("utf-8")
Encoding::UndefinedConversionError: "\xE2\x80\xB0" from UTF-8 to ISO-8859-1

由于字符串本身不携带任何关于它被错误编码的编码的信息,你没有足够的信息来可靠地解决它,并且只能迭代最可能的编码列表和启发式检查使用您的希伯来语启发式每次成功重新编码的结果。

回应我链接的帖子:字符编码很难。

关于ruby - 在 ruby​​ 中处理编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32004631/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com