13

Python 3. 我正在使用 QT 的文件对话框小部件来保存从 Internet 下载的 PDF。我一直在使用“打开”读取文件,并尝试使用文件对话框小部件来编写它。但是,我遇到了“TypeError: '_io.BufferedReader' 不支持缓冲区接口”错误。

示例代码:

with open('file_to_read.pdf', 'rb') as f1: 
    with open('file_to_save.pdf', 'wb') as f2:
        f2.write(f1)

此逻辑在不使用“b”指示符或从 Web 读取文件时(如使用 urllib 或请求)时可正常处理文本文件。这些是“字节”类型,我认为我需要打开文件。相反,它作为缓冲阅读器打开。我尝试了字节(f1),但得到“TypeError:'bytes'对象不能被解释为整数。” 有什么想法吗?

4

3 回答 3

17

如果您的意图是简单地制作文件的副本,您可以使用shutil

>>> import shutil
>>> shutil.copyfile('file_to_read.pdf','file_to_save.pdf')

或者,如果您需要逐字节访问,类似于您的结构,则可以使用:

>>> with open('/tmp/fin.pdf','rb') as f1:
...    with open('/tmp/test.pdf','wb') as f2:
...       while True:
...          b=f1.read(1)
...          if b: 
...             # process b if this is your intent   
...             n=f2.write(b)
...          else: break

但是逐字节可能真的很慢

或者,如果您想要一个可以加快速度的缓冲区(不冒将未知文件大小完全读入内存的风险):

>>> with open('/tmp/fin.pdf','rb') as f1:
...    with open('/tmp/test.pdf','wb') as f2:
...       while True:
...          buf=f1.read(1024)
...          if buf: 
...              for byte in buf:
...                 pass    # process the bytes if this is what you want
...                         # make sure your changes are in buf
...              n=f2.write(buf)
...          else:
...              break

对于 Python 2.7+ 或 3.1+,您还可以使用此快捷方式(而不是使用两个with块):

with open('/tmp/fin.pdf','rb') as f1,open('/tmp/test.pdf','wb') as f2:
    ...
于 2013-05-19T03:18:52.070 回答
5

在另一个文件中写入文件确实没有意义。你想要的是将f1的内容写入f2。您可以使用 f1.read() 获取内容。所以你必须这样做:

with open('file_to_read.pdf', 'rb') as f1: 
    with open('file_to_save.pdf', 'wb') as f2:
        f2.write(f1.read())
于 2013-05-19T12:53:26.707 回答
5

python cookbook

from functools import partial

with open(fpath, 'rb') as f, open(target_fpath, 'wb') as target_f: 
    for _bytes in iter(partial(f.read, 1024), ''):
        target_f.write(_bytes)

partial(f.read, 1024)返回一个函数,每次读取二进制文件1024字节。iter会在遇到 a 时结束blank string ''

于 2016-12-17T14:46:20.657 回答