当我在Python中使用open(filename)或在C中使用fopen(filename)时,保存文件的编码是什么?

时间:2012-10-21 14:43:30

标签: python encoding python-2.7 file-encodings

运行时环境:Python 2.7,Windows 7

注意:我说的是PYTHON源代码生成的文件的编码(不是在谈论PYTHON源文件的编码),在PYTHON源文件DID顶部声明的编码与编码中的编码一致PYTHON源文件已保存。

当字符串(content = 'abc')中没有非ascii字符时,文件(file.txt,而不是PYTHON源文件)在fp.close()之后以ANSI编码保存, PYTHON文件(并以ANSI编码格式保存)内容如下:

## Author: melo
## Email:prevision@imsrch.tk
## Date: 2012/10/12
import os

def write_file(filepath, mode, content):
    try:
        fp = open(filepath, mode)
        try:
            print 'file encoding:', fp.encoding
            print 'file mode:', fp.mode
            print 'file closed?', fp.closed
            fp.write(content)
        finally:
            fp.close()
            print 'file closed?', fp.closed
    except IOError, e:
        print e


if __name__ == '__main__':
    filepath = os.path.join(os.getcwd(), 'file.txt')
    content = 'abc'
    write_file(filepath, 'wb', content)

但是当字符串(content = 'abc莹')中有一些非ascii字符时,文件(file.txt)将在fp.close()之后以UTF-8编码保存,尽管我声明了使用file.txt在PYTHON源文件(不是#encoding=gbk)顶部的编码。此时,PYTHON源文件的内容如下:

# -*- encoding: gbk -*-
## Author: melo
## Email:prevision@imsrch.tk
## Date: 2012/10/12
import os

def write_file(filepath, mode, content):
    try:
        fp = open(filepath, mode)
        try:
            print 'file encoding:', fp.encoding
            print 'file mode:', fp.mode
            print 'file closed?', fp.closed
            fp.write(content)
        finally:
            fp.close()
            print 'file closed?', fp.closed
    except IOError, e:
        print e

if __name__ == '__main__':
    filepath = os.path.join(os.getcwd(), 'file.txt')
    content = 'abc莹'
    write_file(filepath, 'wb', content)

有没有证据表明它的行为如此?

2 个答案:

答案 0 :(得分:2)

文件保存在编码保存。源文件保存在编码保存。它们不一定是同样,它们应该声明

根据您的other question,我假设您正在使用Notepad ++,当您打开file.txt时,您会发现Notepad ++认为该文件是在UTF-8 without BOM中编码的。这是Notepad ++不正确的 guess 。选择中文GB2312字符集,文件将正确显示。

除非用字节顺序标记(BOM)或某些其他元数据提示或由用户告知,否则程序不知道文件的编码是什么。

正确的Python程序会做这些事情:

  1. 如果源文件中使用了非ASCII字符,则声明源文件的编码。
  2. 对所有文本使用Unicode字符串。
  3. 在输出到二进制流(如文件)时对Unicode字符串进行编码。
  4. 从二进制流中读取时将传入的文本数据解码为Unicode。
  5. (可选)使用带字节顺序标记的编码,以便编辑知道文件编码。
  6. 示例:

    # encoding: utf-8
    import codecs
    with codecs.open('file.txt','wb',encoding='utf-8-sig') as f:
        f.write(u'abc莹')
    

    您现在应该在Notepad ++中看到file.txt被检测为编码为'UTF-8'(带有BOM)并正确显示文件。

    请注意,如果您将编码声明为gbk,则可以将文件保存为“ANSI”(系统上的GBK),并且由于使用了Unicode字符串,它仍然可以正常工作。

    实际上,您的系统可能是代码页936(cp936)而不是GBK。它们并不完全相同。最好使用UTF-8或UTF-16等Unicode编码,它可以准确地表示所有Unicode字符。

答案 1 :(得分:1)

# -*- encoding: gbk -*-

位于PYTHON文件的顶部,表示PYTHON文件的编码。使用编解码器 使用codecs模块。

你需要这个:codecs.open()