web-dev-qa-db-ja.com

Pythonバイナリファイルの書き込み、バイト

Python3。QTのファイルダイアログウィジェットを使用して、インターネットからダウンロードしたPDFを保存しています。私は 'open'を使用してファイルを読み取り、ファイルダイアログウィジェットを使用してそれを書き込もうとしています。ただし、「TypeError: '_io.BufferedReader' does not support the buffer interface」エラーが発生しています。

コード例:

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

このロジックは、「b」指定子を使用しない場合、またはurllibやリクエストなどのようにWebからファイルを読み取る場合に、テキストファイルで適切に機能します。これらは「バイト」タイプで、ファイルを開く必要があると思います。代わりに、バッファリーダーとしてオープンしています。私はbytes(f1)を試しましたが、「TypeError: 'bytes'オブジェクトは整数として解釈できません。」と表示されます。アイデアは?

11

単にファイルのコピーを作成することを意図している場合は、 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+では、2つのwithブロックを使用するのではなく)このショートカットを使用することもできます。

with open('/tmp/fin.pdf','rb') as f1,open('/tmp/test.pdf','wb') as f2:
    ...
14
dawg

ファイルを別のファイルに書き込むことは実際には意味がありません。必要なのは、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())
5
Kritzefitz

_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は_blank string ''_に会うと終了します。

4
WeizhongTu