在MySQL查询之前解码ISO-8859-1并编码为UTF-8

时间:2016-07-29 05:16:23

标签: php python mysql utf-8 character-encoding

如果我做得对,我有点卡住了。

我有一个ISO-8859-1的文件(很确定)。我的MySQL数据库采用utf-8编码。这就是为什么我想在将文件作为查询发送之前将文件转换为UTF-8编码字符的原因。例如,首先我使用 file.txt file.txt 的每一行重写为 file_new.txt

line = line.decode('ISO-8859-1').encode('utf-8')

然后我保存它。接下来,我创建一个MySQL连接并使用以下查询创建一个游标,以便以utf-8接收所有数据。

query = 'SET NAMES "utf8"'
cursor.execute(query)

在此之后,我重新打开 file_new.txt 并将每行输入MySQL。这是以MySQL utf-8编码获取表格的正确方法吗?或者我错过了任何关键部分?

现在接收这些数据。我也使用'SET NAMES "utf8""。但是当我将标题内容类型设置为

时,收到的数据会给我一个问号�
header("Content-Type: text/html; charset=utf-8");

另一方面,当我设置

header("Content-Type: text/html; charset=ISO-8859-1");

它工作正常,但来自数据库的其他utf-8编码数据正在被扰乱。因此,我猜测来自 file.txt 的数据仍然没有被编码为utf-8。任何人都可以解释原因吗?

PS:在我读取每行之前,我替换了一个字符并将 file.txt 保存到 file.txt.tmp 。然后我读了这个文件来获取 file_new.txt 。我不知道它是否会对原始文​​件编码造成任何问题。

f1 = codecs.open(tsvpath, 'rb',encoding='iso-8859-1')
f2 = codecs.open(tsvpath + '.tmp', 'wb',encoding='utf8')
for line in f1:
    f2.write(line.replace('\"', '\''))
f1.close()
f2.close()

在下面的示例中,我是utf-8编码的波斯数据,这是正确的,但其他非英语文本将出现在"问号"中。这正是我的问题。

示例:已删除。

4 个答案:

答案 0 :(得分:1)

请改为尝试:

line = line.decode('ISO-8859-1').encode('utf-8-sig')

来自文档:

  

由于UTF-8是8位编码,因此不需要BOM和任何U + FEFF   解码后的字符串中的字符(即使它是第一个字符)是   被视为零宽度无空间。

     

没有外部信息,就无法可靠地确定   哪个编码用于编码字符串。每个charmap编码   可以解码任何随机字节序列。然而,这是不可能的   UTF-8,因为UTF-8字节序列具有不允许的结构   任意字节序列。增加可靠性   可以检测到UTF-8编码,微软发明了UTF-8的变种   (Python 2.5称其为“utf-8-sig”)用于其记事本程序:之前   任何Unicode字符都写入文件,UTF-8编码   BOM(看起来像字节序列:0xef,0xbb,0xbf)是   书面。因为任何charmap编码文件都不太可能   从这些字节值开始(例如映射到

)      

拉丁文小写字母I DIAERESIS RIGHT-POINTING DOUBLE ANGLE   iso-8859-1中的报价标记反转问号,这增加了   可以正确猜测utf-8-sig编码的概率   从字节序列。所以这里没有使用BOM   确定用于生成字节序列的字节顺序,但是   一个有助于猜测编码的签名。关于编码   utf-8-sig编解码器将写入0xef,0xbb,0xbf作为前三个字节   到文件。在解码时,如果utf-8-sig将跳过这三个字节   显示为文件中的前三个字节。在UTF-8中,使用了   不鼓励使用BOM,一般应避免使用。

来源:https://docs.python.org/3.5/library/codecs.html

修改

样品: "Hello World".encode('utf-8')产生b'Hello World'"Hello World".encode('utf-8-sig')产生b'\xef\xbb\xbfHello World'突出显示文档:

  

编码时   utf-8-sig编解码器将写入0xef,0xbb,0xbf作为前三个字节   到文件。在解码时,如果utf-8-sig将跳过这三个字节   显示为文件中的前三个字节。

修改 在将文件转换为utf-8编码之前,我已经做了类似的功能。这是一个片段:

def convert_encoding(src, dst, unicode='utf-8-sig'):
    return open(dst, 'w').write(open(src, 'rb').read().decode(unicode, 'ignore'))

根据您的示例,试试这个:

convert_encoding('file.txt.tmp', 'file_new.txt')

答案 1 :(得分:1)

欢迎来到unicode和windows的精彩世界。我发现这个网站非常有助于理解我的字符串http://www.i18nqa.com/debug/utf8-debug.html出了什么问题。您需要的另一件事是像HxD这样的十六进制编辑器。有很多地方可能出问题。例如,如果您正在文本编辑器中查看文件,它可能会尝试提供帮助,并默默地更改您的编码。

从原始数据开始,在HxD中查看并查看编码是什么。在Hxd中查看结果,看看是否正在进行更改。重复整个过程中的步骤。

如果没有完整的代码和示例数据,很难说问题出在哪里。我的猜测是你用二元文件上的单引号代替双引号是罪魁祸首。

另请查看The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) by Joel Spolsky

答案 2 :(得分:0)

好吧,伙计们,所以我的编码是正确的。该文件正在根据需要编码为utf-8。所有的询问都是正确的。事实证明,阿拉伯语中的其他数据集符合ISO-8859-1标准。因此,其中只有一个在工作。无论我做了什么。

Hexeditors确实提供了帮助。但最后我只使用了崇高的文本来重新检查我的编码数据是否为utf-8。事实证明,python脚本和sublime编辑器做了同样的事情。所以代码很好。 :)

答案 3 :(得分:0)

需要进行任何显式编码或解码。 SET NAMES ...应该匹配客户端编码(对于INSERTing)或应该成为(对于SELECTing)。

MySQL将在客户端编码和列CHARACTER SET之间进行转换。