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

2024-04-27 00:43:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在研究将二进制文件的字节映射到另一组字节的函数。我在同一个文件中读写。我的问题是每次我这样做都会得到额外的字节,除非我在关闭文件之前移到文件的末尾,下面是我的代码:

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()时遇到了相同的问题。我不明白为什么“魔术线”能解决问题,因为它从来没有用过。我会很感激我能在这方面得到的任何见解。在


Tags: 文件inselfsourceforsize字节newline
2条回答

评论(答案如下):

我看到了和你一样的行为:

#!/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())

输出(在f.write之后使用幻线或缓冲=0或f.flush())

^{pr2}$

输出(无魔线)

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中的bug)。在

经过一点实验,我猜想这是Python3中的一个bug。在

为了支持我的推测,我提供了以下代码(基于@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())

当使用Python2.7.1运行时,它的工作方式与您预期的一样,并且魔术线没有任何区别。在

当使用python3.1.2运行时,它莫名其妙地需要神奇的no op seek()才能使其按预期工作。在

在这一点上,我建议向核心python3开发人员演示代码,以获得他们对这是否是一个bug的意见。在

相关问题 更多 >