limodou的学习记录
limodou是一个程序员,他关心的焦点是Python, DocBook, Open Source ...

导航

Blog统计
  • 文章 - 927
  • 收藏 - 0
  • 评论 - 2911
  • Trackbacks - 16
公告

文章

收藏

    相册

      DocBook

      python

      Pythoner in 中国

      Python开源项目

      技术

      其它

      我的东东

      我的开源项目

      存档


      正在读取评论……
       

      对于有Unicode的程序,如果我们需要将Unicode内容写入文件中,一般直接保存是不行的,需要将其转成相应的本地编码然后再保存。方法可以是:

      text = '中国'
      utext = unicode(text, 'cp936')
      outtext = utext.encode('cp936')
      open('test.txt', 'w').write(outtext)

      如果我们在保存文件时,编码是灵活指定的,可以将上述方法进行改造,为:

      def savefile(text, encoding):
          outtext = text.encode(encoding)
          open('test.txt', 'w').write(outtext)

      也就是说将编码作为一个参数。

      不过,上面的情况都是重新打开一个文件,而且完全处于自已的掌握之下。如果我们在调用其它的函数,函数要求一个文件对象,这个函数会自动调用文件对象的write方法,你无法自已进行码制转换的处理时应该怎么办呢?为什么会有这样的问题呢?我是在使用 wxPython 中的 xrecd 工具(生成xml格式的xrc资源文件的工具)时发现这一问题。

      问题的出现是这样的。我正在研究如何实现国际化的处理,由于在 NewEdit 中部分对话框我使用了xrc资源文件,因此对于它们我不能直接使用gettext进行提取和转换。于是我想对于不同的语言我可以定义不同的资源文件,基本内容一样,就是文本信息是根据语言的不同而不同。这样在转换时,我可以根据当时的语言选择与之对应的资源文件,从而完成不同语言的转换。那么首先我要使用xrecd来生成不同编码的资源文件(其实,也可以直接对资源文件进行修改),如:英文的、中文的。但当我修改了原来是英文的某些文本,encoding也指定为了'cp936',一保存,程序报错。改成英文的就没有错。跟踪到程序是保存xml文件时的writexml函数出错了。writexml是minidom的一个方法,它可以将一棵dom树保存到文件中。虽然我在xrecd已经指定了编码的类型,但这个编码只是要写到xml文件的头中,minidom的处理并不用它对要保存的内容进行编码的转换。现在我使用的 wxPython 是unicode(在windows下)版本,因此在 xrecd 中的所有东西都是unicode编码。就象我上面说过,直接保存unicode是不行的,需要转换。但由于writexml方法并不进行编码转换,因此当保存内容是unicode时,程序就出错了。再仔细看一下writexml方法吧:

      def writexml(self, writer, indent="", addindent="", newl=""):

      它是一个顶层函数,你主要需要传递给它一个文件对象(writer,其它参数用于输出漂亮的格式),对于要写入的文本它会自动进行处理,因此,留给你能做的只是如何修改writer了。象前面的先对编码进行转换,再写入文件中,这种语句你是无法控制的(除非你改写原来的minidom.py程序)。怎么修改writer呢?的确可以修改,这也是我刚学会的。方法就是使用codecs模块。示例代码如下:

      1    f = open(filename, 'wb')
      2    writer = codecs.lookup('cp936')[3](f)
      3    dom.writexml(writer)

      第一行先生成一个文件对象。

      第二行是调用codecs模块中的lookup方法,它会返回一个指定的编码的四元组:(编码函数、解码函数、编码用的流reader对象,解码用的流writer对象)。这里我们要用的就是解码用的流writer对象。经过第二行语句的处理,我们得到了一个新的文件对象(流对象),这个对象会对所有传入给它的文本先进行编码再调用原来的流对象(这里就是文件对象)进行真正的保存。

      第三行我们传入新的流对象,这样会将所有的内容保存为'cp936'的编码。而且我们不再需要自已进行解码的处理了。



      Trackback: http://tb.donews.net/TrackBack.aspx?PostId=27834


      [点击此处收藏本文]  发表于2004年06月12日 6:53 PM




      正在读取评论……
      大名
      网址
      验证码
      评论