Python3(v3.2.2)在写二进制文件时的额外位

时间:2011-10-26 06:14:54

标签: python python-3.x binaryfiles

我一直致力于将二进制文件的字节映射到另一组字节的函数。我正在阅读并写入同一个文件。我的问题是,每次我这样做,我最终会得到额外的字节,除非我在关闭之前移动到文件的末尾,这是我的代码:

with open(self._path,'r+b') as source:
    for lookAt in range(0,self._size[1]*self._size[2],1):
        source.seek(lookAt*self._size[0],0)
        readBuffer = array.array('B')
        readBuffer.fromfile(source, self._size[0])
        newLine = array.array('B',[mappingDict[mat] for mat in readBuffer])
        source.seek(lookAt*self._size[0],0)
        newLine.tofile(source)
        source.seek(0,2) # Magic line that solves stupid bug
source.close()

我使用数组模块读取和写入数据,因为当我使用read()和write()时遇到了同样的问题。我不明白为什么'魔术系'解决了这个问题,因为它从未使用过。我将非常感谢能够获得的任何见解。

2 个答案:

答案 0 :(得分:3)

评论(答案如下):

我看到的行为和你一样:

#!/usr/bin/env python3
import os
import sys

filename = '/tmp/a'
with open(filename, 'wb') as f:
    f.write(b'1234a67b8ca')
print(open(filename, 'rb').read())

bufsize = 3

table = bytes.maketrans(b'abcde', b'xyzzz') # mapping
with open(filename, 'r+b') as f:
    for i in range(0, os.path.getsize(filename), bufsize):
        f.seek(i, os.SEEK_SET)
        b = f.read(bufsize) # result shouldn't depend on it due to 1 -> 1
        if not b: 
            break
        f.seek(i, os.SEEK_SET)
        f.write(b.translate(table))
        f.seek(0, os.SEEK_END) # magic
print(open(filename, 'rb').read())

输出(使用魔术线或缓冲= 0或f.wush后的f.flush())

b'1234a67b8ca'
b'1234x67y8zx'

输出(没有魔术线)

b'1234a67b8ca'
b'1234a67b8zx1234x67y8'

答案:

如果你的映射是1 - > 1你可以使用bytes.translate()

#!/usr/bin/env python3
import io
import os
import sys

filename = '/tmp/a'
data = b'1234a67b8ca'*10000
with open(filename, 'wb') as f:
    f.write(data)
assert data == open(filename, 'rb').read()
print(data[:10]+data[-10:])

bufsize = io.DEFAULT_BUFFER_SIZE

table = bytes.maketrans(b'abcde', b'xyzzz') # mapping
with open(filename, 'r+b') as f:
    while True:
        b = f.read(bufsize) # result shouldn't depend on bufsize due to 1 -> 1
        if not b: 
            break
        f.seek(-len(b), os.SEEK_CUR)
        f.write(b.translate(table))
        f.flush()

tr_data = data.translate(table)
assert tr_data  == open(filename, 'rb').read()
print(tr_data[:10]+tr_data[-10:])

如果没有flush()io.BufferedRandom似乎无法interlaced read/seek/write(Python3中的错误)。

答案 1 :(得分:1)

稍微尝试了一下,我猜想这是Python 3中的一个错误。

为了支持我的推测,我提供以下代码(基于@ J.F.Sebastian's):

import os
import sys

filename = '/tmp/a'
with open(filename, 'wb') as f:
    f.write(b'1234a67b8ca')
print(open(filename, 'rb').read())

bufsize = 3

with open(filename, 'r+b') as f:
    for i in range(0, os.path.getsize(filename), bufsize):
        f.seek(i, os.SEEK_SET)
        b = f.read(bufsize)
        f.seek(i, os.SEEK_SET)
        f.write(b)
#        f.seek(0, os.SEEK_END) # magic
print(open(filename, 'rb').read())

使用Python 2.7.1 运行时,它会按照您的预期运行,并且魔术线没有任何区别。

使用Python 3.1.2 运行时,莫名其妙地需要神奇的无操作seek()才能使其按预期工作。

此时我建议向Python 3开发人员展示代码,以了解这是否确实是一个bug。