【问题标题】:How to determine if I should encode or not when changing connection charset?更改连接字符集时如何确定是否应该编码?
【发布时间】:2012-08-14 09:02:19
【问题描述】:

我有一个 MySQL 设置,其中所有表/字段和字符集设置都是 UTF-8,除了来自 SqlAlchemy 的连接。

我最近将连接字符集更改为UTF-8,以便在任何地方使用UTF-8

更改此设置时,DB中的旧值会呈现错误,例如:

Björn => Björn

这个没问题,我只是把值收集起来编码,用python中的encode方法,再放回去。

当我尝试转换设置更改后插入的值时出现问题,这些值已经正确。

有没有一种好方法来确定我是否应该对值进行编码?

【问题讨论】:

  • 没有可靠的方法来仅根据数据猜测编码 - 编码检测非常棘手,并且根据您的语料库,您可能会得到误报。

标签: python mysql encoding sqlalchemy


【解决方案1】:

您的旧编码大概是拉丁语 1?

您可能可以通过查看连续字节来检测字符串何时使用 Latin-1 而不是 UTF-8 编码。 UTF-8 标准有一个distinctive codepage layout,我们可以用它来检测一段文本是用 Latin-1 还是 UTF-8 编码的:

  • 00-7F 范围内的任何字节都是安全的,当然,这些是 ASCII 值,并且这些代码点在两种编码之间匹配。这里没有帮助,不需要帮助。

  • 字节 C0、C1 和 F5-FF 在 UTF-8 编码中是非法。任何包含这些的字符串都必须是 Latin-1 编码的。

  • C2-DF 范围内的字节必须后跟一个 80-BF 范围内的字节。如果您有任何两个字节与此不匹配,则您可能手上有一个 Latin-1 编码的字符串。

如果您曾经编码的只是 Latin-1 字符(直到 Unicode 代码点 255),您可以在这里停下来;包含 E0-FF 范围内字节的任何内容都是旧的 Latin-1 数据。

如果您在切换后确实添加了 UTF-8 数据,这超出了 Latin-1 范围,您还需要包含以下规则:

  • E0-EF 范围内的字节标记一个 3 字节的 UTF-8 字符。接下来的两个字节必须再次落在 80-BF 范围内。

3 UTF-8 字节数据覆盖了BMP 的其余部分,您不太可能在此之外进行编码。如果您确实在此之外进行编码,请查找:

  • F0-F4 范围内的字节后面必须紧跟 80-BF 范围内的 3 个字节。

如果所有这些条件都匹配,你可能有一个UTF-8字符串,但你不能100%确定。如果其中任何一个 not 匹配,则您肯定有一个 Latin-1 字符串。但是,Latin-1 代码点 C2-DF 不太可能跟随代码点 80-BF,因为后者的大部分要么是控制代码,要么是更深奥的变音符号。也许您可以通过寻找多个 2 字节 UTF-8 序列来进一步缩小范围,以提高您的置信度分数。

因此,总而言之 (tl;dr):您可以通过查看多字节序列来找到 大多数 Latin-1 编码的字符串。如果它们不属于严格的 UTF-8 标准,则您手头上有一个 Latin-1 字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 2010-10-27
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多