【Python】バイナリファイルを読み書きモードで追記する(モードa+b)【入門第71回】

206, 2019-10-01

目次

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

バイナリファイルを読み書きモードで追記するには、まずopen関数のmode引数にa+bを指定します。
このモードのopen関数は開こうとするファイルが存在しない場合はファイルを新規作成してファイルを開きます。
開こうとするファイルが存在する場合はオフセット位置をファイル末尾に移動してファイルを開きます。
このモードのopen関数から得られるファイルオブジェクトはio.BufferedRandomです。
ファイルオブジェクトのreadwriteメソッドを使うとバイナリファイルにデータを読み書きすることが出来ます。

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

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

  • io.BufferedRandomの詳細

  • バイナリファイルにデータを追記する

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

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

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

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

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

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

このモードのopen関数は開こうとするファイルが存在しない場合はファイルを新規作成してファイルを開きます。
開こうとするファイルが存在する場合はオフセット位置をファイル末尾に移動してファイルを開きます。

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

io.BufferedRandomの詳細

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

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

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

<class '_io.BufferedRandom'>

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

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

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

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


バイナリファイルにデータを追記する

たとえば↓のような内容のバイナリファイルalphas.datがあります。

abc

このalphas.datを読み書きモードで開いて追記するには↓のようにwriteメソッドを使います。

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

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

abcdef

a+bモードでファイルを開くと、開いた直後のファイルオブジェクト内のオフセット位置はファイル末尾になっています。
そのためwriteメソッドを単純に使えばそのままファイルに追記することが出来ます。

writeメソッドで書き込めるデータはバイト列かバイト列の類に限られます。
バイト列について詳しく知りたい方は↓の記事をご覧ください。

  • [TODO: リンク(バイト列)]

その他、データの書き込みについて詳しく知りたい方は↓の記事をご覧ください。

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

たとえば↓のような内容のバイナリファイルalphas.datがあります。

abc

a+bモードで開いたファイル、alphas.datからデータを読み込みたい場合は↓のようにreadを使いますが、

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

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

b''

空のデータが返ってきました。
a+bモードでファイルを開くと、開いた直後のファイルオブジェクト内のオフセット位置はファイル末尾になっています。
これはtellメソッドなどで確認することが出来ます。
さきほどのalphas.datを開いて確認してみましょう。

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

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

3

バイナリファイルの場合、tellメソッドはファイル先頭から現在位置までのバイト数を返します。
↑の例ではファイルのオフセット位置は3バイト目になっていますね。
これはabcという内容のバイナリファイルを開いているので、このabc分が3バイトということです。

a+bモードでデータを読み込みたい場合は↓のようにseekメソッドでファイルのオフセット位置をファイル先頭にしてからデータを読み込みます。

import os

with open('alphas.dat', mode='a+b') as fp:
    # ファイルのオフセット位置を先頭に移動する
    fp.seek(0, os.SEEK_SET)

    # ファイル先頭からデータを読み込む
    data = fp.read()
    print(data)

seekメソッドの第1引数には第2引数からの基点位置を指定します。
第2引数にはシークの基点となる定数を渡します。
os.SEEK_SETはファイル先頭を表す定数です。
つまりfp.seek(0, os.SEEK_SET)というのはファイルのオフセット位置を「ファイル先頭から0の位置」に移動する命令というわけです。

その他、データの読み込みについて詳しく知りたい方は↓の記事をご覧ください。

おわりに

a系のモードはw系と比べてファイルを破壊的に開かないので、なかなか安心できるモードと言えます。
うまいこと使い分けるようにしましょう。

以上、次回に続きます。

また見てね

関連動画





スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク