URN Logo
UNIX Resources » Linux » China Linux Forum » Python 编 程 » 4 » 一个内建函数open()的诡异的问题
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.net
  业界新闻与评论
  自由软件杂谈
  IT 人生
  Linux软件快递
  翻译作坊
  Linux图书与评论
  GNU Emacs/XEmacs
  Linux 中文环境和中文化
  Linux桌面与办公软件
  Linux 多媒体与娱乐版
  自由之窗Mozilla
  笔记本电脑上的Linux
  Gentoo
  Debian 一族
  网络管理技术
  Linux 安装与入门
  WEB服务器和FTP服务器
  域名服务器和邮件服务器
  Linux防火墙和代理服务器应用
  文件及打印服务器
  技术培训与认证
  Linux内核技术
  Linux 嵌入技术
  Linux设备驱动程序
  Linux 集群技术
  LINUX平台数据库
  系统和网络安全
  CPU 与 编译器
  系统计算研究所专栏
  Linux下的GUI软件开发
  C/C++编程版
  PHP 技 术
  Java&jsp技术
  Shell编程技术
  Perl 编 程
  Python 编 程
  XML/Web Service 技术
  永远的Unix
  FreeBSD世界
   
一个内建函数open()的诡异的问题
一个内建函数open()的诡异的问题 - zjsflyer [2006-01-22 22:58 | 2,149 byte(s)]
 
 
Re: 一个内建函数open()的诡异的问题 - oyster [2006-01-24 11:57 | 189 byte(s)]
 
Re: 一个内建函数open()的诡异的问题 - zjsflyer [2006-01-23 02:43 | 2,568 byte(s)]
 
Re: 一个内建函数open()的诡异的问题 - panhudie [2006-01-23 18:19 | 323 byte(s)]
 
Re: 一个内建函数open()的诡异的问题 - zjsflyer [2006-01-23 21:14 | 1,028 byte(s)]
 
Subject: 一个内建函数open()的诡异的问题
Author: zjsflyer    Posted: 2006-01-22 22:58    Length: 2,149 byte(s)
[Original] [Print] [Top]
open()函数有时候的表现让人匪夷所思....请看下面例子

环境:windows xp,python 2.4.2

现在有三个文本,分别如下

文件名------------文件内容------字符编码-----------------十六进制编辑模式下的编码(ultraEdit有这个功能)
【ascii.txt】----- abcd----------- ASCII编码--------------- 61 62 63 64
【utf.txt】--------中国a---------- UTF-16-le编码--------- FFFE 2D4E FD56 6100
【gbk.txt】-------中国a---------- GBK编码----------------D6D0 B9F9 61



python内建的 open(filename[,mode[,buffer]]) 函数是用来打开,读写文件的

例如在python自带的IDLE编辑器下写入

>>>myFile = open('d:\temp\ascii.txt', mode='rb')
>>>data = myFile.read()
>>>data
'abcd'

>>>myFile = open('d:\temp\gbk.txt', mode='rb')
>>>data = myFile.read()
>>>data
'xd6 xd0 xb9 xfa a'

但让我觉得不可思议的是下面这个

>>>myFile = open('d:\temp\utf.txt', mode='rb')
>>>data = myFile.read()
>>>data
'xe4xb8xadxe5x9bxbda' #这是“中国a”的utf-8的字符编码


诡异之处在于,以二进制方式打开的utf-16-le(这是windowsNT,2000,Xp下的缺省的unicode编码)

居然在open函数打开的file对象上执行read()方法时自动的转换成了utf-8 的编码了

我一直以为python中的file对象是比较“傻”的,想不到他还能转换编码??? 最麻烦的是,他只能转换

utf-16到utf-8,对别的编码就是按二进制一个字节一个字节老老实实读入...


那以后编写程序时不得不对要读取的文件进行判断,utf-16是一种情况,其他的又是另一种情况,这都麻烦啊,而且有时候你根本不知道读入的文件的编码,那时怎么办?





不知道有没有那位达人解释一下这是怎么回事? 这算不算python的一个bug?
[Original] [Print] [Top]
Subject: Re: 一个内建函数open()的诡异的问题
Author: zjsflyer    Posted: 2006-01-23 02:43    Length: 2,568 byte(s)
[Original] [Print] [Top]
呵呵,又高了一个下午,已经搞清楚了...只能说windows平台下的utf-8编码的unicode文件相当复杂...

居然有三种之多,utf-8号称所以平台都是一样的,但一旦涉及到如何构建一个内容是utf-8编码的文本文件的问题
时,就不是那么回事了.... 以下以windows XP,python2.4.2unicode版本为例,并且假设文件内容都是
“中国a”


1. 用‘记事本’创建,且选择“文件”-->“另存为”,编码选择“UTF-8”.

它的特点是会在文件前隐含增加三个字节“EF BB BF”,只要你用python中的open()并选择二进制模式
打开时,你就会发现它的内容是'xef xbb xbf xe4 xb8 xad xe5 x9b xbd a',

最搞笑的是当你用UltraEditor来打开它,同时右键菜单中选择“Hex 编辑”时,你会发现这个文本的内容居然是“FF FE 2D4E FE56 6100”,这居然和这个文件的utf-16-le的编码完全一样,搞得我最开始还以为记事本不能创建真正的utf-8的文本文件了...

2.用UltraEditor创建,而且选择“文件”-->“转换”-->“ASCII转UTF-8(unicode编辑)”,还有用python中
的 codecs.open(filename, mode='wb', encoding='utf-8') 函数创建的文件是一样的,特点如下

这中utf-8文件不会在在文件前隐含增加三个字节“EF BB BF”,只要你用python中的open()并选择二进制
模式打开时,你就会发现它的内容是'xe4 xb8 xad xe5 x9b xbd a',

同样当你用UltraEditor的”Hex 编辑“来打开它时,你会发现和第一中情况一样,这个文本的内容是“FF FE 2D4E FE56 6100”

3.用UltraEditor创建,而且选择“文件”-->“转换”-->“Unicode/ASCII/UTF-8/转UTF-8(ASCII编辑)“

它的特点是在文本中就是变长字节的utf-8编码,这才像真正的utf-8文档...哈哈

用python中的open()并选择二进制模式打开时,你就会发现它的内容是'xe4 xb8 xad xe5 x9b xbd a',
但当你用UltraEditor的”Hex 编辑“来打开它时,这个文本的内容是“E4B8AD E59BBD 61”





别看这三种utf-8文件都有不相同的地方,但当你在Opera,IE中打开它们,同时选择编码为”UTF-8“时

你会发现他们都是真正的utf-8,因为都能正确显示为”中国a“,而选择UTF-16,GBK等内码时,就显示
为乱码...神了...哈哈.





不过值得庆幸的,utf-16不存在这样的问题...用ultraEditor,记事本,python的codecs.open(...,encoding='utf-16')三者创建的utf-16的文件都是一样的.....

这包括用用UltraEditor的”Hex 编辑“来打开它,和用python中的open()并选择二进制模式
打开时都是一致的...当然,因为是windows os的缘故,它们都是UTF-16-Le 的,即高位字节在后的方式

[Original] [Print] [Top]
Subject: Re: 一个内建函数open()的诡异的问题
Author: panhudie    Posted: 2006-01-23 18:19    Length: 323 byte(s)
[Original] [Print] [Top]
我用gvim试了下用hex模式打开utf16le的文件, 结果跟想的一样.
但是再换成text模式的时候, gvim就会用 根据你的encoding(我设的是cp936), 把文件转成cp936, 而不是utf16le了.

UltraEditor可能就是一开始就帮你转了.

google了下
EFBB 应该是表示utf8

FFFE 这个是utf16le
[Original] [Print] [Top]
Subject: Re: 一个内建函数open()的诡异的问题
Author: zjsflyer    Posted: 2006-01-23 21:14    Length: 1,028 byte(s)
[Original] [Print] [Top]
我想经过这两天的研究,我已经搞明白了Unicode的相关问题...


Unicode文件的头几个字节叫BOM,有两个功能,一是用来指明Unicode文件的编码具体是UTF-16,还是UTF-8,UTF-32的,二是如果是UTF-16或者UTF-32,则BOM可以进一步指出高低位字节的顺序的.


BOM 为 FF EF是,表明该文本文件是UTF-16-le 编码,这就是windowsNT,2000,xp缺省使用的unicode编码方式.

BOM 为EF FF是,表明该文本文件是UTF-16-be 编码

BOM 为EF BB BF时,表明该文件是UTF-8 编码


但这是规定,具体的程序完全可以不遵守的,你可以不在UTF-8编码的文件前加EF BB BF,一样没有问题...这就是python中用codecs.open(..., encoding='utf-8')建立的那种utf-8编码的Unicode文本文件...

而微软自己编写的记事本,当然遵循规范了,所以它创建的utf-8文件,前面是有EF BB BF


还有,UltraEditor的确是做了自动转换的工作,在HEX编辑方式下,它把UTF-8文件的ROM自动省略了(如果有的话),而且自动把UTF-8编码转换为UTF-16-Le来显示....这造成了我以前的那些困惑..
[Original] [Print] [Top]
Subject: Re: 一个内建函数open()的诡异的问题
Author: oyster    Posted: 2006-01-24 11:57    Length: 189 byte(s)
[Original] [Print] [Top]
感谢你的分析
编码我始终没有弄清楚
上回用一个语言,源代码要求是utf-8编码,但是初始化指定字库和程序正文部分的uft-8又是不一样的,那个语言的发明者又死活不承认是bug,郁闷的很
[Original] [Print] [Top]
Subject: Re: 一个内建函数open()的诡异的问题
Author: Aryang    Posted: 2006-03-11 11:21    Length: 8 byte(s)
[Original] [Print] [Top]
建议加精
[Original] [Print] [Top]
« Previous thread
关于try...except的问题
Python 编 程
4
Next thread »
wxGrid使用问题 请问如何去掉grid(0,0)显示的黑框
     

Copyright © 2007 UNIX Resources Network, All Rights Reserved.      About URN | Privacy & Legal | Help | Contact us
备案序号: 京ICP备05006143    webmaster: webmaster@unixresources.net
This page created on 2008-07-17 04:10:57, cost 0.042539119720459 ms.