为了账号安全,请及时绑定邮箱和手机立即绑定

在 Python 中将宽字符转换为系统 ANSI 编码

在 Python 中将宽字符转换为系统 ANSI 编码

RISEBY 2022-06-28 17:12:13
我目前正在努力让我的屏幕阅读器与Becky 一起更好地工作!互联网邮件。我面临的问题与那里的列表视图有关。此控件不支持 Unicode,但项目是在屏幕上自定义绘制的,因此当有人查看它时,无论编码如何,所有字段的内容看起来都不错。当通过 MSAA 或 UIA 访问时,基本 ANSI 字符和使用非 Unicode 程序设置的代码页编码的邮件具有正确的文本,而以 Unicode 编码的邮件则不能。文本示例:黄鹅自己表示为:ZaĹĽĂłĹ,ć gęślÄ... jaźń 在这种情况下,它已损坏 CP1250,如下面的回答。然而:⚠️表示为: ⚠️⏰表示为:⏰,高生旺表示为:é«ç”źć—ş我刚刚假设这些字符串已损坏无法修复,但是当 Windows 10 中的 unicode beta 支持启用时,它们会正确暴露。是否可以在 Python 中模拟这种行为?该解决方案需要同时在 Python 2 和 3 中工作。目前,我只是简单地将这些字符的已知组合替换为它们的正确表示,但这不是很好的解决方案,因为包含替换和要替换的字符的列表需要使用每个新发现的字符进行更新。
查看完整描述

1 回答

?
墨色风雨

TA贡献1853条经验 获得超6个赞

您的 utf-8 被解码为 cp1250。


我在 python3 中所做的是:


orig = "Zażółć gęślą jaźń"

wrong = "Zażółć gęślą jaźń"


for enc in range(437, 1300):

    try:

        res = orig.encode().decode(f"cp{enc}")

        if res == wrong:

            print('FOUND', res, enc)

    except:

        pass

...结果是 1250 代码页。


所以你的解决方案应该是:


import sys


def restore(garbaged):

    # python 3

    if sys.version_info.major > 2:

        return garbaged.encode('cp1250').decode()

    # python 2

    else:

        # is it a string

        try:

            return garbaged.decode('utf-8').encode('cp1250')

        # or is it unicode

        except UnicodeEncodeError:

            return garbaged.encode('cp1250')

编辑:


"高生旺"无法恢复的原因é«ç”źć—ş:


"高生旺".encode('utf-8')是b'\xe9\xab\x98\xe7\x94\x9f\xe6\x97\xba'。


问题是\x98部分。在 cp1250 中,该值没有字符集。如果你试试这个:


"高生旺".encode('utf-8').decode('cp1250')

你会得到这个错误:UnicodeDecodeError: 'charmap' codec can't decode byte 0x98 in position 2: character maps to <undefined>


获取方式"é«ç”źć—ş"为:


"高生旺".encode('utf-8').decode('cp1250', 'ignore')

但是这ignore部分很关键,它会导致数据丢失:


'é«ç”źć—ş'.encode('cp1250')是b'\xe9\xab\xe7\x94\x9f\xe6\x97\xba'。


如果你比较这两个:


b'\xe9\xab\xe7\x94\x9f\xe6\x97\xba'

b'\xe9\xab\x98\xe7\x94\x9f\xe6\x97\xba'

您会看到该\x98字符丢失,因此当您尝试恢复原始内容时,您会得到一个UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 0-1: invalid continuation byte.


如果你试试这个:


'é«ç”źć—ş'.encode('cp1250').decode('utf-8', 'backslashreplace')


结果将是'\\xe9\\xab生旺'。\xe9\xab\x98可以解码为高,从\xe9\xab它是不可能的。


查看完整回答
反对 回复 2022-06-28
  • 1 回答
  • 0 关注
  • 279 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信