Python写入文本文件时‘GBK’编码器无法编码字符‘uXXYY‘

Python写入文本文件时‘GBK’编码器无法编码字符‘uXXYY‘,第1张

Python写入文本文件时‘GBK’编码器无法编码字符‘uXXYY‘

文章目录
  • (一)现象
  • (二)分析
    • 2.1 确认文件编码和业务逻辑
    • 2.2 编程就是Googleing stackoverflow……
    • 2.3 继续分析
  • (三)解决
  • (四)进一步分析

(一)现象

如题,报错类似:

‘gbk’ codec can’t encode character ‘uXXYY’ in position ZZ: illegal multibyte sequence

(二)分析 2.1 确认文件编码和业务逻辑

比较奇怪的地方,这些报错的内容是从另一个文本中读取出来的,读取时指定了GBK编码且并没有错。
用其它文本工具打开看过,文件确实也不是UTF8的。
部分代码如下,下面写入时报的错:

...
		dfboss = spark.read.csv(sys.argv[1] + 'zk.cm_customer*.txt', sep='|', encoding='GBK')
        rddBOSS = dfboss.rdd.map(lambda r: (r[0], (r[1], r[2], r[3]))).reduceByKey(lambda x, y: x)
        countBOSS = rddBOSS.count()
        print("数据[营业客户]: %i" % countBOSS, flush=True)

        dfhss = spark.read.csv(sys.argv[1] + 'zg.crm_customer*.txt', sep='|', encoding='GBK')
        rddCRM = dfhss.rdd.map(lambda r: (r[0], (r[1], r[2], r[3]))).reduceByKey(lambda x, y: x)
        countCRM = rddCRM.count()
        print("数据[账务客户]: %i" % countCRM, flush=True)
...
...
		f001 = open('./C_CUSTOMER_001_0.TXT', "w", encoding='GBK')
        output001 = out_b_s.filter(lambda lk: lk[1][1] is None).collect()
        for (kk, (v1, v2)) in output001:
            try:
                f001.write("%s|%s|%s|%sn" % (kk, v1[0], v1[1], v1[2]))
                g001 += 1
            except Exception as err:
                print(err, file=sys.stderr)

        f001.close()
...

并且只有少量行报错,绝大多数是正确的。

2.2 编程就是Googleing stackoverflow……

网上搜到的解决方案大概是:

  1. 文件编码设置错误,排除……
  2. 改Python编码,Python3已经默认UTF8了。py文件和pycharm设置UTF8,排除……
  3. 版本?3.6和3.10现象一致,排除……
  4. 手动处理错误,没有针对本质,排除……
  5. 手动处理不能自动处理的编码,总感觉不对,排除……
2.3 继续分析

同样的数据,用Java和C++处理均无问题。
说明编码应该是正确的呀。

那么只能推断编码部分和解码,实现得不一样。

上面代码中,解码是:

dfboss = spark.read.csv(..., encoding='GBK')

编码是:

f001 = open(..., ..., encoding='GBK')

那么是不是Java和C++,以及前面的spark看到GBK的时候,判断内容是中文国标编码
而下面的open文件方法严谨的使用了GBK编码呢?
纯猜的……

(三)解决

突然想到,GBK并不是最新的汉字编码规范,于是试了一下GB18030。
居然就OK了!

f001 = open(..., ..., encoding='GB18030')

(四)进一步分析

GBK用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间。
所以前面的uE502确实不再编码范围内。

但是打开用GB18030正确输出的文本后,并没有发现uE502,以及其它之前报的错误编码。

E5好说,这个02也太过分了,太低了吧。
再看看GB18030……

所以虽然用了GB18030就不报错了。
但问题到底是怎么产生的,是转换过程中出现了错误么?
是否读写前后的中文都是正确的没有变化呢???烦恼啊……

后来的追加测试:
试了一下用gb2312,产生了比gbk多得多的错误。
我觉得这个现象说明有字在gb2312,gbk范围外,
也间接说明ufffd是转换中产生的错误,而不是本身字符的编码:)

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5690320.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存