【Python】バイナリファイルの読み込み方法を初心者向けにわかりやすく解説

はじめに

Pythonでバイナリファイルを読む場面は、画像データを扱ったり、自作のファイル形式を解析したりするときなど、実務でもよくあります。
一方でテキストファイルに比べると扱いが少し特殊なため、初心者の方は戸惑うかもしれません。
今回の記事では、そうした戸惑いを解消するために、バイナリファイルの基本的な仕組みや読み込みの方法を、短いコード例を交えながら解説します。

具体的な用途の例としては、画像編集ツールを開発するときに画像のバイナリデータを読み込んで処理するケースや、暗号化された情報を復号して活用する場面などが挙げられます。
この記事では、そういった実際の業務シーンにも関連づけながら、分かりやすくまとめていきます。

この記事を読むとわかること

  • テキストファイルとバイナリファイルの違い
  • Pythonでバイナリファイルを開くときの基本的な記述
  • 代表的な読み込み方法と実務での活用例
  • バイナリデータを分割して読み込む方法や注意点
  • 実務でも使われるファイル解析のヒント

バイナリファイルとは何か

バイナリファイルとは、コンピューターが理解しやすい0と1の組み合わせで構成されたファイル形式のことです。
テキストファイルと違い、人間がそのまま見ると意味不明な文字列に見える場合が多いでしょう。
イメージとしては、画像や動画、音声ファイル、実行ファイルなどがバイナリ形式で保存されている典型例です。

一般的にテキストファイルは改行文字やスペースなどがそのまま読み取れますが、バイナリファイルではそうした改行やスペースがデータとして含まれている場合があります。
また、文字エンコーディングを気にしなくてもよい代わりに、データを正しく読み取るための構造や長さを把握しておく必要があります。

テキストファイルのように単純にprint()しても中身がわかるわけではありません。
そのため、後述するようにバイナリモードでファイルを開き、専用の処理を行うことがよくあります。

Pythonでバイナリファイルを読み込む基本の手順

Pythonでバイナリファイルを扱う場合、ファイルを開くときのモード指定がポイントです。
テキストファイルであれば "r""w" を使いますが、バイナリファイルでは "rb""wb" といったバイナリモードで開く必要があります。

with構文で安全に開く

Pythonではwith open(ファイル名, モード) as 変数:という構文を用いると、ファイルのクローズを自動で行ってくれます。
バイナリモードで開く場合は、以下のように書きます。

with open("example.bin", "rb") as f:
    data = f.read()
    # 読み込んだデータを使って何か処理する

"rb"は「読み込み専用のバイナリモード」を示しています。
この例では、ファイルをすべて読み込んでdataに格納しています。
画像ファイルなどに対して行う場合は、バイナリデータとして扱われるため、文字列とは扱い方が異なります。

読み込んだバイナリデータの扱い

f.read()で得られるdataは、bytes型として扱われます。
このbytesはバイナリ列を表すオブジェクトで、テキストデータのように直接文字列として印字しても意味がわからない記号が出てくることがあります。
ただ、画像などを処理する場合は、そのbytesを加工するための外部ライブラリを使ったり、独自フォーマットを解析したりして必要な情報を抽出します。

実務であれば、例えばバイナリファイルの先頭に格納されたヘッダ情報だけを取り出して、フォーマットのバージョンを確認するケースもあるでしょう。
次の見出しで、部分的にデータを読み込む例も紹介します。

バイナリファイルを部分的に読み込む方法

ファイル全体ではなく、一部のデータだけを読み取りたい場面も多いです。
例えば、大きなファイルの先頭数バイトだけがヘッダ情報になっている場合があります。
そんなときはf.read(バイト数)のようにして、読み取りたいサイズを指定すると便利です。

with open("example.bin", "rb") as f:
    header = f.read(10)  # 先頭の10バイトを読み込む
    # ヘッダ情報を解析して必要な処理を行う
    body = f.read(50)    # 続けてさらに50バイトを読み込む

このように必要な部分だけを区切って読み取ることで、大きなファイルを効率よく扱うことができます。
実務では、ファイルの構造がドキュメントなどで定義されている場合があるので、そのルールに沿ってバイトオフセットやサイズを決め打ちすることも珍しくありません。

読み込み位置を変更する

ファイルポインタを操作して、特定の位置へジャンプするにはf.seek(移動先のバイト数)を使います。
例えばヘッダを読み取った後、次の特定位置までスキップしたい場合などに便利です。

with open("example.bin", "rb") as f:
    header = f.read(10)
    f.seek(20)  # 20バイト目に移動
    chunk = f.read(10)

このように、seek()を活用して任意の場所からバイナリを読み込む方法は、複数のデータブロックが連続しているファイル構造を解析するときなどに役立ちます。

ファイル解析やデータ抽出の実務イメージ

バイナリファイルの読み込みは、単純にファイル全体を取得するだけで終わらず、後続の解析処理が伴うことが多いです。
例えば、画像ファイルであればヘッダに格納されている幅や高さなどの情報を取り出して表示させることも考えられます。
また、暗号化ファイルであれば、読み込んだバイナリを復号ライブラリに渡して、中身を取り出す場面もあるでしょう。

こうしたバイナリ解析は、ファイル形式の仕様書を読み解きながら実装する作業です。
具体例として、以下のような流れが挙げられます。

1. ヘッダ部分(例えば最初の128バイト)を読み込む
2. ヘッダからフォーマット識別子やファイルバージョンを抽出する
3. ボディ部分を読み込む前に、必要に応じてファイルポインタを移動する
4. ボディ部分を一定サイズごとに解析し、情報を取り出す

このように、Pythonのopen()でバイナリモードを指定したうえで、read()seek()を組み合わせると柔軟な処理ができます。

バイナリファイルの解析では、あらかじめファイルのフォーマット仕様を確認しておくと手戻りが少なくなります。

バイナリデータと構造体の読み込み

バイナリファイルの中には、数値や文字列などが混在していることがよくあります。
これを構造体として読み取る場合は、Python標準ライブラリのstructモジュールを活用することが多いです。
例えば、ファイルの先頭4バイトに整数値が入っている場合などに役立ちます。

import struct

with open("example.bin", "rb") as f:
    data = f.read(4)  # 整数1つ分(4バイト)を読み込み
    value = struct.unpack("<I", data)[0]  # リトルエンディアンのunsigned intとして解析
    # ここでvalueに読み取った整数が格納される

ここでの"<I"は、リトルエンディアン形式の4バイト整数を表すフォーマット指定です。
structモジュールを使うことで、バイナリ上のデータを数値や文字列などに変換でき、実務でも解析や計算処理がしやすくなります。

実務での利用イメージ

例えばセンサーデータを取得するプログラムでは、バイナリ形式で取得した計測値を構造体として読み込み、値を取り出してグラフ化することが考えられます。
また、独自のファイルフォーマットを使っている社内システムのログ解析を行う際などに、structモジュールを組み合わせると便利でしょう。

バイナリファイルを安全に扱うための注意点

バイナリファイルは直接内容が見えにくいため、想定外の形式だった場合にエラーが発生したり、不正なデータを読み込んでしまうこともあります。
そうしたリスクを下げるために、以下のようなポイントに注意してください。

例外処理を入れる

ファイルが存在しなかったり、権限がない場合、open()時点でエラーになることがあります。
try-exceptブロックなどで例外をキャッチすると、安定した動作につながります。

ファイルのサイズを事前に確認する

予期せぬ大容量ファイルが入力されると、メモリ不足に陥る可能性があります。
必要に応じて、部分読み込みを使って安全に処理しましょう。

想定フォーマットと異なるデータが混ざる可能性

仕様書通りでないファイルが渡されると、struct.unpack()などでエラーが発生することもあります。
その場合は、ファイルヘッダをチェックして正しいフォーマットであるかを確認する作りにしておくと安心です。

想定外のデータ構造を読み込むと処理結果がおかしくなるリスクがあります。 あらかじめファイル仕様に合わせたバリデーションを行いましょう。

まとめ

Python バイナリファイル 読み込みに焦点を当てて、基礎から実務での活用シーンを意識した方法まで解説しました。
ファイルをバイナリモードで開くことで、テキストファイルとは異なる形でデータを扱うことができます。

特に、open()のモード指定("rb")や、必要に応じた部分読み込み、ファイルポインタの移動、structモジュールを活用した解析といったテクニックは、画像処理やファイル解析などのシステム開発で重宝されます。

初心者の方もまずは小さめのバイナリファイルで試し、自分が扱いたいデータ形式の仕様を調べながら進めてみると理解が深まるでしょう。
必要なデータだけを読み込みたい場合のread(バイト数)seek()の使い方、数値に変換する際のstructの使い方を覚えておくと、さまざまなバイナリ解析に応用できます。

これをきっかけに、より複雑なファイル形式や画像、暗号化ファイルなどにも挑戦してみてください。

Pythonをマスターしよう

この記事で学んだPythonの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。