如何将已经两次UTF-8编码的字符串解码为简单的UTF-8?

时间:2009-09-19 18:02:38

标签: c# mysql utf-8

我有一个巨大的MySQL表,其行以UTF-8编码两次。 例如,“Újratárgyalja”存储为“Újratárgyalja”。

MySQL .Net连接器以这种方式下载它们。我尝试了许多与System.Text.Encoding.Convert()的组合,但没有一个有效。

发送set names 'utf8'(或其他字符集)无法解决问题。

如何将它们从双UTF-8解码为UTF-8?

3 个答案:

答案 0 :(得分:8)

奇怪的问题,但我认为我可以通过UTF-8和Latin-1的适当混合来重现它(不仅仅是两次使用UTF-8而没有在Latin-1中散布错误的步骤)。这是整个奇怪的往返,“那里又回来了”(Python 2. *或IronPython都应该能够重现这一点):

# -*- coding: utf-8 -*-
uni = u'Újratárgyalja'
enc1 = uni.encode('utf-8')
enc2 = enc1.decode('latin-1').encode('utf-8')
dec3 = enc2.decode('utf-8')
dec4 = dec3.encode('latin-1').decode('utf-8')

for x in (uni, enc1, enc2, dec3, dec4):
  print repr(x), x

这是有趣的输出......:

u'\xdajrat\xe1rgyalja' Újratárgyalja
'\xc3\x9ajrat\xc3\xa1rgyalja' Újratárgyalja
'\xc3\x83\xc2\x9ajrat\xc3\x83\xc2\xa1rgyalja' Ãjratárgyalja
u'\xc3\x9ajrat\xc3\xa1rgyalja' Ãjratárgyalja
u'\xdajrat\xe1rgyalja' Újratárgyalja

Ã开头的奇怪字符串显示为enc2,即两个utf-8编码,其中散布的latin-1解码投入到混合中。正如您所看到的那样,它可以通过完全相反的操作序列来解除:解码为utf-8,重新编码为latin-1,再次解码为utf-8 - 原始字符串又回来了(yay) !)。

我相信Latin-1(又名ISO-8859-1)和UTF-8的正常往返属性应该保证这个序列能够正常工作(抱歉,没有C#可以立即尝试使用该语言,但我希望编码/解码序列不应该依赖于使用的特定编程语言。

答案 1 :(得分:1)

当你写“MySQL .Net连接器以这种方式下载它们时”。这很有可能这意味着MySQL .Net连接器认为它正在向Latin讲述Latin-1,而MySQL认为会话是UTF-8。该列也有可能被声明为Latin-1,但实际上包含UTF-8数据。

如果是后者(标记为Latin-1的列,但数据实际上是UTF-8),如果您使用MySQL的文本处理函数,列上的ORDER BY或其他情况,您将收到神秘的排序规则问题和其他错误文本“意味着什么”,而不仅仅是通过网络发送的字节。

在任何一种情况下,你都应该尝试解决潜在的问题,尤其是因为对于那些必须维护系统的人来说,这将是一个彻头彻尾的头痛。

答案 2 :(得分:-1)

您可以尝试使用

SELECT CONVERT(`your_column` USING ascii)
FROM `your_table`

在MySQL查询级别。不过,这是在黑暗中刺伤。