yakczh_cu 发表于 2014-02-03 22:42

读进内存的utf8文件内容的str 和代码文件中的str有什么不同吗?

本帖最后由 yakczh_cu 于 2014-02-03 23:01 编辑

# -*- encoding=utf-8 -*-
text="中文"
print(type(text))
print(text)这样输出结果是对的# -*- encoding=utf-8 -*-
text="中文524μg/m³"
print(text)这样就报错: (unicode error) 'utf8' codec can't decode byte 0xd6 in position 0: invalid continuation bytefile=r'u8.html'# 将字符串写到utf8编码的文件
text=open(file, 'r', encoding='utf-8').read()
print(type(text))
print(text)这样输出报错
   print(text)
UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff' in position 0: illegal multibyte sequenc

这两个text有什么不一样的吗?

timespace 发表于 2014-02-04 12:28

很遗憾,你描述的例子在我这里完全正常,尤其是第三个例子的错误中,‘gbk’是哪里来的?

timespace 发表于 2014-02-04 12:53

原则很简单:当一个对象在内存与IO之间转换时,字符编码就会起作用

以Python 3为例。源文件编码应该是utf-8,如果当前编辑器环境(通常继承自OS默认编码)不是utf-8,那么直接输入非ASCII字符(比如中文)就会有问题,因为解释器无法将文件的字符内容转换为内存表示(IO字节流 ---decode=xxx--> 内存内部UNICODE)。str和bytes是严格区分的,所以print(str)不会出现Python 2中那种编码错误(内存内部UNICODE ---encode=xxx--> IO字节流)

第三个例子十分莫名其妙,‘gbk’从什么地方来的?还有'\ufeff'这是utf-16的BOM,怎么和这里的utf-8搅和到一块的?最好详细描述下你的环境,并提供你的测试代码和文件,否则没得搞。

yakczh_cu 发表于 2014-02-04 14:47

回复 2# timespace


    gbk 是win32平台控制台的下的编码, http://apoo.bokee.com/7028948.html这里有解释

yakczh_cu 发表于 2014-02-04 15:00

本帖最后由 yakczh_cu 于 2014-02-04 15:01 编辑

回复 3# timespace


环境是win7 python3
测试代码是
# -*- encoding=utf-8 -*-
text="中文524μg/m³"
print(text)这个文件是用utf8编码的,
这个字符串本来是抓取的html文件里的内容,因为保存成utf8的时候加了bom,一开始是报错'\ufeff' 后来我把这个bom去掉了,还是报错,就直接硬编码到测试代码里
过程经历了远程网页 -》 本地文件(bom) ->本地文件(去掉bom)-> 硬编码   这几个阶段 每个步骤都会报错
后来发现是 m³的这个立方的字符的问题在gbk环境下输出进行编码转换的时候会直接报异常
在ve2x论坛上得到的答案是 不要在win32的cmd调试程序
http://v2ex.com/t/98936#reply20
但我认为这是python3的坑,同样的unicode,同样的字节码,同样的跨平台,在java程序中输出就是正常的

timespace 发表于 2014-02-04 15:54

回复 5# yakczh_cu
能否把你本地转换的文件上传下?因为你直接在浏览器里贴内容,浏览器会自动转换编码,可能不是你原来的实际内容。


   

timespace 发表于 2014-02-04 16:02

过去调试的时候,我也曾经无数次的怀疑过编译器或操作系统的问题,不过最终都是自己打脸:-L

timespace 发表于 2014-02-04 17:15

仔细看了下ve2x,然后做了几个测试。

1. 直接原因。win的控制台编码是gbk,但'3'的定义超出了gbk,不过还在gb18030中,所以按照gbk输出报错是合理的。bash-3.2 $python3
Python 3.3.3 (v3.3.3:c3896275c0f6, Nov 16 2013, 23:39:35)
on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> text="中文524μg/m3"
>>> text[-1]
'3'
>>> c = text[-1]
>>> c.encode('gbk')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'gbk' codec can't encode character '\xb3' in position 0: illegal multibyte sequence
>>> c.encode('gb2312')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'gb2312' codec can't encode character '\xb3' in position 0: illegal multibyte sequence
>>> c.encode('gb18030')
b'\x810\x856'
>>> hex(ord(c))
'0xb3'2. Java行,而Python却不行?Java做IO,可能做了适配,比如gbk表示不了的字符,切换到更大的字符集如gb18030。

坦白说,这个问题说明不了任何关于系统和语言的优劣。Win为了照顾本地编码方式而用了码区落后的gbk,Python严格尊重控制台字符编码并符合UNIX传统的‘宽进严出’原则,Java为了方便而适配也没错。

yakczh_cu 发表于 2014-02-04 17:36

回复 6# timespace


   

timespace 发表于 2014-02-04 17:58

继续补充下,Windows的CLI(console)完全是垃圾,加上PowerShell也是垃圾,是十足的二等公民,GUI才是正统,而UNIX/Linux正好相反。
页: [1]
查看完整版本: 读进内存的utf8文件内容的str 和代码文件中的str有什么不同吗?