2007-03-11

前回からの続き。

前回の話は、まとめると、現状では、codecs.open で開いたファイルはプラットフォームごとの改行コードの違いを吸収してくれない、ということでした。

しかたないので、codecs モジュールで使われているクラスを継承して、間に入って改行コードの変換をやらせてみることにしました。こんな感じで……。

class StreamReaderWriter(codecs.StreamReaderWriter):

    def __init__(self, stream, Reader, Writer, errors, linesep=os.linesep):
        codecs.StreamReaderWriter.__init__(self,
                                           stream, Reader, Writer, errors)
        self.linesep = linesep
    
    
    def read(self, size=-1):
        return self.reader.read(size).replace(self.linesep, '¥n')
    
    def readline(self, size=None):
        return self.reader.readline(size).replace(self.linesep, '¥n')

    def readlines(self, sizehint=None):
        return [line.replace(self.linesep, '¥n') for line
                in self.reader.readlines(sizehint)]

    def next(self):
        return self.reader.next().replace(self.linesep, '¥n')

    def write(self, data):
        return self.writer.write(data.replace('¥n', self.linesep))

    def writelines(self, list):
        return self.writer.writelines([line.replace('¥n', self.linesep)
                                       for line in list])


def interface(fp, encoding, errors='strict', linesep=os.linesep):
    reader, writer = codecs.lookup(encoding)[2:]
    return StreamReaderWriter(fp, reader, writer, errors, linesep)


def open(filename, mode, encoding=None, errors='strict', bufsize=1,
         linesep=os.linesep):
    if not encoding:
        fp = file(filename, mode, bufsize)
    else:
        if 'b' not in mode:
            mode += 'b'
        fp = interface(file(filename, mode, bufsize),
                       encoding, errors, linesep)
        fp.encoding = encoding
    return fp

ダウンロード (codecs2-0.1.0.zip)

まだ実運用はしてないので使いものになるかどうかはわからないけど、簡単にテストした限りではこれでよさそうです。