• dream
    2024-09-03 来自重庆
    文章中的解码示例,我再 ubuntu python3 中运行有点问题,需要在字符串前面加 b: ``` >>> '\xd6\xd0\xce\xc4\xb7\xfb\xba\xc5'.decode('gbk') Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'str' object has no attribute 'decode'. Did you mean: 'encode'? >>> >>> print '\xd6\xd0\xce\xc4\xb7\xfb\xba\xc5'.decode('gbk') File "<stdin>", line 1 print '\xd6\xd0\xce\xc4\xb7\xfb\xba\xc5'.decode('gbk') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)? >>> >>> b'\xd6\xd0\xce\xc4\xb7\xfb\xba\xc5'.decode('gbk') '中文符号' >>> print(b'\xd6\xd0\xce\xc4\xb7\xfb\xba\xc5'.decode('gbk')) 中文符号 >>> ```
    展开

    作者回复: 是的,python3和python2在处理字符编码时,有一些区别。 感谢补充这些内容。

    
    
  • 123
    2024-09-03 来自浙江
    老师,请教几个问题: 1、“总结一下,写入数据时,如果 character_set_client 的设置和数据的实际编码不一致,就可能会产生乱码,或者在写入数据时直接报错” mysql是如何判断character_set_client和数据的实际编码不一致,在传入的时候会有编码信息字段吗? 2、“这说明了 MySQL 容忍了文本编码从 character_set_client 转换到 character_set_connection 时的错误。但如果往存储引擎中写入数据时编码转换有问题,语句就会失败,数据无法写入到数据库。” 实验环境:utf8终端,character_set_client=gbk,character_set_connection=utf8, table charset=utf8 CREATE TABLE `t_utf8_2` ( `a` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 (1) “中文字符”.encode('utf8').decode('gbk').encode('utf8') 可以存入数据,但是显示数据乱码; (2) set names = gbk => character_set_client=gbk;character_set_connection=gbk;character_set_results=gbk; 应该也是“中文字符”.encode('utf8').decode('gbk').encode('utf8') ?个人理解是通过终端的字符集进行编码,然后通过connection字符集进行解码,最后在根据table charset进行编码进行存储? 所以为什么当终端charset != character_set_client = character_set_connection != table charset 会报错? 以上的情况分别为: 1> 插入乱码:终端charset[utf8] != character_set_client[gbk] != character_set_connection[urf8] = table charset[urf8] 2> 插入报错:终端charset[utf8] != character_set_client[gbk] != character_set_connection[gbk] != table charset[urf8] 3> 插入正常:终端charset[utf8] = character_set_client[utf8] != character_set_connection[gbk] != table charset[urf8] 对于情况3,“如果 character_set_connection 和 character_set_client 设置不一样,MySQL Server 端会将数据转换成 character_set_connection 指定的字符集。” 但是在我的环境中也是正常的,mysql8.0.29
    展开

    作者回复: 1. MySQL在使用character_set_client指定的编码对数据进行decode时,如果遇到问题,就说明字符集不匹配了。 MySQL并不知道客户端发过来的数据的真实编码,除非使用_charset指定,比如: mysql> SELECT _utf8mb4 0xe4b8ade69687; | 中文 | 2. utf8环境下,如果character_set_client设置为gbk,那么表的字符集为gbk和utf8时,会有不一样的情况。 mysql> create table t_gbk(a varchar(100)) charset gbk; mysql> create table t_utf8(a varchar(100)) charset utf8; mysql> set names gbk; mysql> insert into t_gbk values('中文符号'); mysql> select a, hex(a), char_length(a) from t_gbk; | 中文符号 | E4B8ADE69687E7ACA6E58FB7 | 6 | 写入到t_gbk时,没有做编码转换。虽然看上去没乱码,但是实际上表里存的是“中文符号”的utf8编码。 为了写入t_utf8,需要设置非严格模式 mysql> set sql_mode=''; mysql> insert into t_utf8 values('中文符号'); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> show warnings; | Warning | 1366 | Incorrect string value: '\xAD\xE6\x96\x87\xE7\xAC...' for column 'a' at row 1 | 数据虽然写入了,但是有warning,Incorrect string value里面显示的十六进制串,来自原始数据“中文符号”的utf8编码,'\xe4\xb8\xad\xe6\x96\x87\xe7\xac\xa6\xe5\x8f\xb7' 用gbk decode这串数据时遇到问题了。 mysql> select a, hex(a), char_length(a) from t_utf8; | �?��符号 | E6B6933FE69E83E7BB97EFB980E5BDBF | 6 | 表t_utf8里存的数据是怎么来的呢? >>> '\xe4\xb8\xad\xe6\x96\x87\xe7\xac\xa6\xe5\x8f\xb7'.decode('gbk', errors='replace').encode('utf8') '\xe6\xb6\x93\xef\xbf\xbd\xe6\x9e\x83\xe7\xbb\x97\xef\xb9\x80\xe5\xbd\xbf' 这个数据和表里的数据有一点差异,就是替换符不一样,MySQL中以\x3f作为替换符。python中以\xef\xbf\xbd,也就是u'\ufffd'作为替换符。这其实就是?和�的区别。

    
    
  • Shelly
    2024-09-02 来自广东
    思考题: 1. 是因为你的终端的字符集为utf8,创建表插入数据时由于设置了set names = gbk,由于表的字符集也是gbk,所以数据存储到表时字符集没有发生转换(但实际是按utf8字符集存储的),你查询时,由于character_set_results为gbk和表的字符集一致,所以字符集没有发生转换,正好你客户端的字符集是utf8,于是中文字符就被阴差阳错的正确显示了出来。 2. 由于你的同事终端的字符集是gbk,当把服务器端的字符集设置成utf8时,查询时,由于character_set_results=utf8和表gbk的字符集不一致,所以需要字符集转换,先要用gbk字符集解码实际用utf8存储的数据,再用utf8进行编码发送到客户端,于是显示就乱码了。 当把服务器的字符集设置成gbk时,由于character_set_results=gbk和表gbk的字符集一致,不存在字符集转换,客户端实际收到是的用utf8字符集编码的数据,终端用GBK字符集解码utf8编码的数据,所以也发生了乱码。 3. 解决方法:把你同事终端的字符集改utf8,服务器端设置set names=gbk;显示中文就不会出现乱码。
    展开

    作者回复: 完美地还原了事发现场👍👍 这种数据,最好还是要订正回来,否则后患无穷。

    
    