【Python】バイナリファイルを読み書きモードで開く(モードr+b)【入門第67回】

198, 2019-09-26

目次

バイナリファイルを読み書きする

こんにちは、narupoです。

バイナリファイルを読み書きモードで開くにはopen関数のmode引数にr+bを指定します。
このモードのopen関数から得られるファイルオブジェクトはio.BufferedRandomです。
ファイルオブジェクトのメソッドを使うとファイルを読み書きすることが出来ます。

今回は具体的には↓を見ていきます。

  • バイナリファイルを読み書きモードで開く

  • io.BufferedRandomの詳細

  • バイナリファイルからデータを読み込む

  • バイナリファイルへデータを書き込む

ほかのファイル入出力についての入門記事は↓をご覧ください。

バイナリファイルを読み書きモードで開く

↓のような内容のバイナリファイルalphas.datがあるとします。

abc

このバイナリファイルを読み書きモードで開くにはopen関数を↓のように使います。

with open('alphas.dat', mode='r+b') as fp:
    pass

open関数の第1引数にファイルのパスを指定します。
mode引数には文字列r+bを指定します。

ファイルが存在しなかった場合、このモードのopen関数は例外FileNotFoundErrorを送出します。

try:
    with open('not-found', mode='r+b') as fp:
        pass
except FileNotFoundError as e:
    print('ファイルが見つかりません')
    print(e)

↑のコードの実行結果は↓のようになります。

ファイルが見つかりません
[Errno 2] No such file or directory: 'not-found'

open関数の詳しい使い方については↓の記事をご覧ください。

io.BufferedRandomの詳細

r+bモードのopen関数から得られるファイルオブジェクトは_io.BufferedRandomです。

with open('alphas.dat', mode='r+b') as fp:
    print(type(fp))

↑のコードの実行結果は↓のようになります。

<class '_io.BufferedRandom'>

公式のドキュメントは↓です。

io.BufferedRandomio.BufferedReaderおよびio.BufferedWriterを継承したクラスです。

io.BufferedReaderおよびio.BufferedWriterはそれぞれio.BufferedIOBaseを、io.BufferedIOBaseio.IOBaseを継承しています。

これらのクラスの公式ドキュメントを参照すれば利用できるメソッドを一望することが出来ます。

バイナリファイルからデータを読み込む

バイナリファイルからデータを読み込むにはファイルオブジェクトのreadメソッドなどを使います。
たとえば↓のような内容のバイナリファイルalphas.datがあるとします。

abc

このバイナリファイルからデータを読み込むには↓のようにします。

with open('alphas.dat', mode='r+b') as fp:
    data = fp.read()
    print(data)

↑のコードの実行結果は↓のようになります。

b'abc'

readが返すデータはバイト列です。
b'abc'はPythonのバイト列で、先頭にbytesbが付いていますね。
バイト列について詳しく知りたい方は↓の記事をご覧ください。

  • [TODO: リンク(bytes)]

その他、バイナリファイルの読み込みについて詳しく知りたい方は↓の記事をご覧ください。

バイナリファイルへデータを書き込む

バイナリファイルにデータを書き込むにはファイルオブジェクトのwriteメソッドを使います。
たとえば↓のような内容のバイナリファイルalphas.datがあるとします。

abc

このファイルに書き込みをするには↓のようにします。

with open('alphas.dat', mode='r+b') as fp:
    fp.write(b'def')

↑のコードを実行するとalphas.datの中身は↓のようになります。

def

abcというデータが上書きされてしまってますね。
r+bモードでは開いた直後のファイルのオフセット位置はファイルの先頭になっています。
tellメソッドでファイルのオフセット位置を確認してみます。

with open('alphas.dat', mode='r+b') as fp:
    print(fp.tell())

↑のコードの実行結果は↓のようになります。

0

このため、ファイルを開いた直後にwriteメソッドを使うと、writeはファイル先頭から書き込んでいくため、既存のデータが上書きされます。
ファイルに追記したい場合は↓のようにしてseekメソッドを使ってファイルのオフセット位置をファイルの末尾に移動してからwriteを使います。

import os

with open('alphas.dat', mode='r+b') as fp:
    # オフセット位置をファイル末尾に移動
    fp.seek(0, os.SEEK_END)

    # ファイル末尾に追記する
    fp.write(b'def')

os.SEEK_ENDはファイル末尾を表す定数です。
seekの第1引数にはその基点位置からの相対位置を渡します。
つまり↑はファイル末尾から0の位置にファイルのオフセット位置をシークさせています。
言いかえればただの「ファイル末尾」という意味ですね。

バイナリファイルへのデータの書き込みついて詳しく知りたい方は↓の記事をご覧ください。

おわりに

今回からいよいよバイナリファイルのランダムアクセスについて踏み出しました。
バイナリファイルのランダムアクセスは、一般的に初心者の方にはちょっと難しいと言われています。
ですので、初心者の方は出来なくてもガッカリしないでください。
私もむか~し初心者のころ、バイナリファイルのランダムアクセスにチャレンジしたことがありますが、まったくできなかった記憶があります。
初心者の方はじっくりできるようになってみてください。

フォースの道は長く険しい

以上、次回に続きます。

また見てね

関連動画





スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク