我一直致力于将二进制文件的字节映射到另一组字节的函数。我正在阅读并写入同一个文件。我的问题是,每次我这样做,我最终会得到额外的字节,除非我在关闭之前移动到文件的末尾,这是我的代码:
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()时遇到了同样的问题。我不明白为什么'魔术系'解决了这个问题,因为它从未使用过。我将非常感谢能够获得的任何见解。
答案 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())
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。