【问题标题】:Python Reading From and Writing to Binary FilesPython 读取和写入二进制文件
【发布时间】:2014-01-07 05:49:59
【问题描述】:

以下是我的问题重新措辞

读取二进制文件的前 10 个字节(稍后操作)-

infile = open('infile.jpg', 'rb')
outfile = open('outfile.jpg', 'wb')
x = infile.read(10)
for i in x:
    print(i, end=', ')
print(x)
outfile.write(bytes(x, "UTF-8"))

第一个打印语句给出 -

255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 

第二个打印语句给出-

b'\xff\xd8\xff\xe0\x00\x10JFIF'

x 中值的十六进制解释。

outfile.write(bytes(x, "UTF-8"))

返回 -

TypeError: encoding or errors without a string argument

那么x一定不是普通字符串而是字节字符串,还是可以迭代的?

如果我想将 x 的内容原封不动地写入 outfile.jpg,那么我就去 -

outfile.write(x)

现在我尝试获取每个 x [i] 并对每个 x [i] 执行一些操作(如下所示为 1 的简单乘积),将值分配给 y 并将 y 写入 outfile.jpg 使其与 infile 相同.jpg。所以我尝试-

infile = open('infile.jpg', 'rb')
outfile = open('outfile.jpg', 'wb')
x = infile.read(10)

yi = len(x)
y = [0 for i in range(yi)]

j = 0
for i in x:
    y [j] = i*1
    j += 1

for i in x:
    print(i, end=', ')

print(x)

for i in y:
    print(i, end=', ')

print(y)

print(repr(x))
print(repr(y))

outfile.write(y)

第一个打印语句(遍历 x)给出 -

255, 216, 255, 224, 0, 16, 74, 70, 73, 70,

第二个打印语句给出-

b'\xff\xd8\xff\xe0\x00\x10JFIF'

第三个打印语句(遍历 y)给出 -

255, 216, 255, 224, 0, 16, 74, 70, 73, 70,

打印语句给出-

[255, 216, 255, 224, 0, 16, 74, 70, 73, 70]

最后,按照 Tim 的建议,打印 repr(x) 和 repr(y) 分别给出 -

b'\xff\xd8\xff\xe0\x00\x10JFIF'
[255, 216, 255, 224, 0, 16, 74, 70, 73, 70]

并且文件写入语句给出了错误-

TypeError: 'list' does not support the buffer interface

我需要的是 y 与 x 的类型相同,这样 outfile.write(x) = outfile.write(y)

我凝视着蟒蛇的眼睛,但还是看不到它的灵魂。

【问题讨论】:

  • 看看这篇文章:stackoverflow.com/questions/5471158/… 似乎 String 类在 Python 2 和 Python 3 之间发生了变化。
  • Hunter - 我用 outfile.write(s.encode('UTF-8') 替换了 outfile.write(s) 并且没有收到错误!但是使用 infile.read() 导致 outfile.jpg大小是 infile.jpg 的两倍并且损坏。我要完成的是读取二进制文件,执行操作,反转该操作并将输出写入单独的文件,以使它们相同。
  • 我链接的帖子中的答案使用了outfile.write(bytes(s, "UTF-8"));

标签: file python-3.x binary


【解决方案1】:

它们根本不完全相同——它们只是在将str() 应用于它们之后显示完全相同(print() 隐含地这样做)。打印其中的repr(),您会看到不同之处。示例:

>>> x = b'ab'
>>> y = "b'ab'"
>>> print(x)
b'ab'
>>> print(y) # displays identically
b'ab'
>>> print(repr(x)) # but x is really a 2-byte bytes object
b'ab'
>>> print(repr(y)) # and y is really a 5-character string
"b'ab'"

混合字符串和字节对象没有意义(好吧,不是在没有明确编码的情况下 - 但你不是试图在这里编码/解码任何东西,对吧?)。如果您使用的是二进制文件,那么您根本不应该使用字符串 - 您应该使用 bytesbytearray 对象。

所以问题不在于你的写作方式:在那之前逻辑基本上是混乱的。

猜不出你想要什么。请编辑问题以显示一个完整、可执行的示例,说明您尝试要完成的工作。我们不需要 JPG 文件——组成一些简短的、任意的二进制数据。喜欢:

dummy_jpg = b'\x01\x02\xff'

【讨论】:

  • 哇,repr() 表明存在差异。我将不得不重新考虑我正在尝试做的事情的逻辑。
【解决方案2】:

...这就是您在 Python 中以二进制模式读取和写入文件的方式。

#open binary files infile and outfile
infile = open('infile.jpg', 'rb')
outfile = open('outfile.jpg', 'wb')

#n = bytes to read
n=5

#read bytes of infile to x
x = infile.read(n)

#print x type, x
print()
print('x = ', repr(x), type(x))
print()

x = b'\xff\xd8\xff\xe0\x00' 类'字节'

#define y of type list, lenth xi, type list
xi = len(x)
y = [0 for i in range(xi)]

#print y type, y
print('y =', repr(y), type(y))
print()

y = [0, 0, 0, 0, 0] 类'列表'

#convert x to 8 bit octals and place in y, type list
j=0
for i in x:
    y [j] = '{:08b}' .format(ord(i))
    j += 1

#print y type, and y
print('y =', repr(y), type(y))
print()

y = ['11111111', '11011000', '11111111', '11100000', '00000000'] 类'列表'

#perform bit level operations on y [i], not done in this example.

#convert y [i] back to integer
j=0
for i in y:
    y [j] = int(i, 2)
    j += 1

#print y type, and y
print('y =', repr(y), type(y))
print()

y = [255, 216, 255, 224, 0] 类'列表'

#convert y to type byte and place in z
z = bytearray(y)

#print z type, and z
print('z =', repr(z), type(z))
print()

z = bytearray(b'\xff\xd8\xff\xe0\x00') 类'bytearray'

#output z to outfile
outfile.write(z)

infile.close()
outfile.close()
outfile = open('outfile.jpg', 'rb')

#read bytes of outfile to x
x = outfile.read(n)

#print x type, and x
print('x =', repr(x), type(x))
print()

x = b'\xff\xd8\xff\xe0\x00' 类'字节'

#conclusion:  first n bytes of infile = n bytes of outfile (without bit level operations)

outfile.close()

【讨论】:

    【解决方案3】:

    感谢您的澄清!你想要的很简单,但你真的需要阅读 bytesbytearray 类型的文档。您想要的是与以下内容有关的任何事情:

    • Unicode
    • 字符串
    • 编码
    • 解码

    这些在这里都完全无关紧要。您从头到尾都有二进制数据,需要坚持使用bytes 和/或bytearray 对象。两者都是字节序列(range(256) 中的“小整数”); bytes 是不可变序列,bytearray 是可变序列。

    那么x一定不是普通的字符串,而是字节串,还是可以迭代的?

    阅读文档 ;-) x 不是“字符串”;执行此操作以查看其类型:

    print(type(x))
    

    这将显示:

    <class 'bytes'>
    

    它是一个bytes 对象,如前所述。这是一个序列,所以是的,它是可迭代的,就像所有序列一样。您还可以对其进行索引、切片等。

    您的y 是一个列表。唉,我不知道你想用它来完成什么。

    我需要的是 y 与 x 的类型相同,这样 outfile.write(x) = outfile.write(y)

    不,您不需要 xy 是同一类型。您确实希望能够将y 写入二进制数据。为此,您需要创建一个 bytes bytearray 对象。这很容易;只需执行以下操作之一:

     y = bytes(y)
    

     y = bytearray(y)
    

    然后

    outfile.write(y)
    

    会做你想做的。

    尽管如上所述,我不知道您为什么要在这里创建一个列表。创建相同列表的一种更简单的方法是跳过所有循环并编写:

     y = list(x)
    

    如果我通过了,你应该开始怀疑你对这里发生的事情的心理模型太复杂,而不是太简单。您正在想象实际上并不存在的困难 :-) 从二进制文件中读取会为您提供 bytes 对象(如果您想读取二进制文件来填充 bytearray 对象,请参阅文件 .readinto() 方法),而写入二进制文件需要给它一个 bytesbytearray 对象来写入。仅此而已。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多