Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

jupyter notebookでバイナリファイルをゴリゴリ操作したいときに見る記事【Python】

Posted at

すーみそー
sumiso_c0db8cだ。

今回は、何故かバイナリファイルの解読が必要になったとき、Pythonを利用して調査するのに使ったコードをまとめました。

各コードブロックを1つのセルとして実行できるように記載します。

Jupyter Notebookとは

Pythonなどのコードを「セル」単位で実行できるインタラクティブな開発環境です。コードをセル単位で実行・修正・再実行ができ、ファイルの読み書きを試行錯誤するのに便利です。

VScodeでファイルの拡張子を.ipynbとするとnotebook形式で表示されます。Pythonの実行環境にライブラリjupyterの追加が必要です。

# pipでインストール
pip install jupyter

# uvの場合
uv add jupyter

詳しい使い方は解説記事を探してください。

バイナリファイルとは

0と1のビット列で構成されたデータファイルです。テキストファイルとは異なり、人間が直接読めない形式です。pngなどの画像や、Excelのファイルもバイナリファイルです。AIに渡すと、コンテキストによっては解読してみせたりします。

本記事ではバイナリファイルの読み書きをjupyter notebook上で行います。
各セルをコピペで動作確認できるようにしましたので、お試しください。

ファイル読み込み

はじめにバイナリファイルの読み込みから。
基本的にテキストファイルの読み込みと同じですが、モードにバイナリのbを添えます。

filepath = 'b\sumiso.dat'
# ファイルを読み込む
with open(filepath, 'rb') as f:
    data = f.read()

data
出力例
b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'

バイト列が表示されます。\xe3は1バイトのデータを16進数で表現したものです。コピペするときは、1バイトの塊ごとコピーします。

ファイル書き出し

データを処理して最終的に書き出したいときに。
読み込みの時と同様に、モードにバイナリのbを添えます。

binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
# ファイルを書き出す
with open("b\sumiso.dat", "wb") as f:
    f.write(binary)

デコード

バイナリを指定のエンコードで文字列に戻します。

# デコード
binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
binary.decode('utf-8')
出力
'すみそ'

エンコード間違えるとエラーになります。

# デコード
# utf-8
binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
binary.decode('shift-jis')
出力
UnicodeDecodeError: 'shift_jis' codec can't decode byte 0x9d in position 8

エンコード

文字列をバイト列に変換します。

# エンコード
name = 'すみそ'
name.encode('utf-8')
出力
b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'

エンコードが異なると出力も変わります。

# エンコード
name = 'すみそ'
name.encode('shift-jis')
出力
b'00\x82\xb7\x82\xdd\x82\xbb'

アルファベットの場合、見た目ほぼ変わりませんがデータ型はバイナリ列になります。

name = 'sumiso_c0db8c'
name.encode('utf-8')
出力
b'sumiso_c0db8c'

デコードできます。

b'sumiso_c0db8c'.decode('utf-8')
出力
'sumiso_c0db8c'

数値のエンコード to_bytes

よく文字列のデータの前に、そのデータの長さを指定のバイト数で記載するパターンがあります。後続のデコード処理で、文字列の境界を正しく認識するためです。そのようなときの長さの部分のエンコード例です。

バイナリデータの長さ自体はlenで取得できます。

# 長さを取得
binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
len(binary)
出力
9

長さを10進数から、バイナリデータに変換します。
バイト数とバイトオーダーを指定します。

# 長さを取得
binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
# 2バイト、リトルエンディアン
len(binary).to_bytes(2, 'little')
出力
b'\t\x00'

バイトオーダーとは、マルチバイトのデータをバイト列として格納する際の並び順です。リトルエンディアンとビッグエンディアンがあります。リトルエンディアンとビッグエンディアンでは並び順が逆になります。

# 長さを取得
binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
# 2バイト、ビッグエンディアン
len(binary).to_bytes(2, 'big')
出力
b'\x00\t'

数値のエンコード struct.pack

標準ライブラリのstructを使用しても、バイト列にエンコードできます。

import struct
# 長さを取得
binary = b'\xe3\x81\x99\xe3\x81\xbf\xe3\x81\x9d'
# リトルエンディアン unsigned short(2バイト)
struct.pack('<H', len(binary))
出力
b'\t\x00'

フォーマット文字によって、バイト数やバイトオーダーを指定できます。

# import struct
number = 12639116

display('リトルエンディアン unsigned long long(8バイト)')
display(struct.pack('<Q', number))

display('ビックエンディアン unsigned int(4バイト)')
display(struct.pack('>I', number))

displayは変数や戻り値をそのまま出力する関数です。

出力
'リトルエンディアン unsigned long long(8バイト)'
b'\x8c\xdb\xc0\x00\x00\x00\x00\x00'

'ビックエンディアン unsigned int(4バイト)'
b'\x00\xc0\xdb\x8c'

数値のデコード

反対に、長さ部分をデコードする例です。フォーマット文字はエンコードのときと同様です。

# import struct
c0db8c = b'\x8c\xdb\xc0\x00\x00\x00\x00\x00'

# リトルエンディアン unsigned long long(8バイト)
struct.unpack('<Q', c0db8c)[0]
出力
12639116

まとめ

本記事では、jupyter notebookでバイナリファイルの内容を調査・解析するための基本的な手法をまとめました。

  • バイナリファイルの読み書き
    open()関数のモードに'rb'や'wb'を指定して、bytes型としてデータを扱います。
  • 文字列とバイト列の変換
    文字列オブジェクトの.encode()でバイト列に、バイト列オブジェクトの.decode()で文字列に変換します。この際、エンコーディングの指定が必須です。
  • 数値のバイト列変換
    整数型の.to_bytes()や標準ライブラリstructを使って、数値(長さなど)をバイト列に変換します。

この記事で紹介した基本操作は、より複雑なファイルフォーマットを解析するための土台となります。ぜひ、次は実際のファイル(例:PNG, GIF, カスタムデータ形式)の仕様書を入手し、struct.unpackなどを活用して、ファイルヘッダーやデータブロックの解析に挑戦してみてください。

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?