Pythonでバイナリファイルを読み込む
- 作成日: 2021-04-19
- 更新日: 2023-12-24
- カテゴリ: Python
Pythonでバイナリファイルを読み込む
Pythonではファイルを開いてデータを読み込むという操作を行うことができます。
具体的には読み込むファイルはテキストファイルとバイナリファイルの2種類です。
バイナリファイルを読み込むには↓のようにコードを書きます。
with open('file.dat', 'rb') as fin:
data = fin.read()
print(data)
具体的に↑のコードについて解説していきます。
バイナリファイルとは何なのか?
ファイルとは、データの単位の1つです。
ファイルを使うとディスクにデータを書き込んだり、逆に読み込んだりが出来るようになります。
このファイルは大きく分けて2種類あります。
それは↓のような種類です。
- テキストファイル
- バイナリファイル
このうち、バイナリファイルはテキストファイルを内包します。
つまり大枠としてはバイナリファイルが基本となるファイルになるわけです。
バイナリファイルはバイト列の集まりのファイルです。
バイトはビットの集まりなので、バイナリファイルはビットの集まりと表現することも出来ます。
今のところ機械が理解できるデータは0
と1
の2種類、つまり電圧の高低ですが、この0
と1
を使ってデータを表現することを2進数(バイナリ)といいます。
0
と1
が並べられたモノがバイナリファイルで、これにフォーマットを付けたものがテキストファイルです。
open()でバイナリファイルを開く
↓のようなファイルを用意します。
1234
abcd
↑のファイルは「file.dat
」として保存しておきます。
普通のエディタで作成していただいてOKです。
Pythonでファイルを開くにはopen()
関数を使いますが、open()
関数には開きたいファイルのファイル名と、そのファイルの開き方であるモードを指定する必要があります。
結論から言うとバイナリファイルを開きたい場合は、モードにはrb
を指定します。
rb
はread binary
の頭文字だと思われます。
つまり↓のようなフォーマットでopen()
を使います。
fin = open('file.dat', 'rb')
fin
というのが開いたファイルオブジェクトです。fin
はfile input
の略です。
ファイルは開いたら閉じないといけません。これは他の言語でも共通のルールかと思います。
理由は、リソースの解放という意味があります。
ファイルを閉じるにはファイルオブジェクトのclose()
を使います。
fin = open('file.dat', 'rb')
fin.close()
このclose()
を自動的にやってくれるのがwith
文です。
with
文でファイルを開けば、with
のブロックが終了した時点で自動的にファイルが閉じられます。
with open('file.dat', 'rb') as fin:
pass
バイナリファイルのファイルオブジェクトの詳細
バイナリファイルを開いた時のファイルオブジェクト(fin
)の種類はtype()
で確認することができます。
↓のように確認します。
with open('file.dat', 'rb') as fin:
print(type(fin))
↑の結果は↓になります。
<class '_io.BufferedReader'>
_io.BufferedReader
はモードrb
で開いたときのファイルオブジェクトのタイプです。
このBufferedReader
のメソッドでよく使われるのはpeek()
とread()
です。
これについては後述します。
BufferedReader
はBufferedIOBase
とIOBase
を継承したクラスです。
よってこの2つのクラスのメソッドを使うことができます。
- io - BufferedIOBase --- ストリームを扱うコアツール — Python 3.9.2 ドキュメント
- io - IOBase --- ストリームを扱うコアツール — Python 3.9.2 ドキュメント
バイナリファイルからデータを読み込む
モードrb
で開いたバイナリファイルからデータを読み込むにはメソッドを使う必要があります。
データを読み込むメソッドには代表的なものにpeek()
とread()
があります。
この2つについて解説します。
peek()でバイト列を読み込む
peek()
とread()
の大きな違いは、read()
が読み込んだ後に読み込み位置を進めるのに対して、peek()
は読み込み位置を進めずに読み込みを行う点です。
ファイルから同じ内容のデータを何度も読み込みたい場合はpeek()
が適していると言えます。
with open('file.dat', 'rb') as fin:
print(fin.peek())
print(fin.peek())
print(fin.peek())
↑のコードを実行すると↓のような結果になります。
b'1234\nabcd'
b'1234\nabcd'
b'1234\nabcd'
peek()
の引数に読み込みたいサイズを渡すと読み込むサイズを指定することができるらしいですが、筆者の環境(Windows, Python3.9.2)では期待した結果は得られませんでした。
公式ドキュメントにも
返されるバイト数は、要求より少ないかもしれませんし、多いかもしれません。
とあるので、あまり指定には信頼性がないのかもしれません。
read()でバイト列を読み込む
read()
は読み込みと同時に読み込み位置を進行させるメソッドです。
read()
に引数を指定しない場合はread()
はEOF
または読み込みがブロックされるまで読み込みます。
with open('file.dat', 'rb') as fin:
print(fin.read())
↑の結果は↓になります。
b'1234\nabcd'
read()
の第1引数に読み込みたいバイト数を指定すると、そのバイト数だけ読み込んで読み込み位置を進めます。
with open('file.dat', 'rb') as fin:
print(fin.read(2)) # 2バイトだけ読み込む
print(fin.read(4)) # 4バイトだけ読み込む
print(fin.read()) # 全部読み込む
↑の結果は↓になります。
b'12'
b'34\na'
b'bcd'
読み込み位置をマニュアルで変更したい
ここでは範囲外になるので解説しませんが、読み込み位置をマニュアルで変更することをランダムアクセスファイルといいます。
これはファイルオブジェクトのseek()
メソッドを使ってファイルの読み込み位置を変更する技術です。
おわりに
今回はバイナリファイルの読み込み方法を解説しました。
バイナリファイルを読み込めるようになれると、低レイヤ―な処理も書けるようになります。
ソケット通信などにも使える技術です。
🦝 < 目が`0`と`1`になる
🐭 < バイナリ目