- 技術 💻
バイナリエディタとは|使い方・おすすめとxxdで読む実例・戻し方
結論
バイナリエディタとは、ファイルの中身を1バイトずつ16進数で表示・編集するソフトです。文字にならないデータも、そのまま見て書き換えられます。
この記事でわかること
- OS別のおすすめ7本と選び方の判断表
- PNG・ZIP・exeなど12形式の先頭バイトの実物
- 書き換え→元に戻す手順と、壊れる原因5つ
ファイルは、0〜255 の数(バイト)が並んだものです。バイナリエディタは、その並びを「位置(アドレス)・16進数・文字」の3列にして見せ、変えたバイトだけを書き換えて保存します。
flowchart TD
A[ファイル<br>0〜255 のバイトの並び] --> B[バイナリエディタで開く]
B --> C[位置・16進数・文字<br>の3列で表示]
C --> D[16進数の欄で<br>値を上書き]
D --> E[変えたバイト以外は<br>そのまま保存]
急いでいる人向けに、よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| バイナリエディタとは | バイトを16進数で見て直すソフト | バイナリエディタとは |
| Windows のおすすめ | HxD・VS Code の Hex Editor | おすすめと選び方 |
| Mac のおすすめ | Hex Fiend・VS Code の Hex Editor | おすすめと選び方 |
| インストールせずに見る | xxd・hexdump・od・Format-Hex | コマンドで中身を見る |
| 見方 | 左から位置・16進数・文字の3列 | 16進数とバイトの見方 |
| ファイルの種類を知る | 先頭のマジックナンバーを見る | マジックナンバー |
| 書き換えて戻す | バックアップ→xxd -r→cmp で確認 | 書き換えて元に戻す |
| 開いたら壊れた | テキストとして保存した・挿入した | よくある失敗 |
確認環境:Ubuntu 24.04.4。ファイルの表示と書き換えは xxd 2023-10-25(vim 9.1.0016 付属)・hexdump(util-linux 2.39.3)・od(GNU coreutils 9.4)・file 5.45・hexyl 0.8.0・hexedit 1.6・vim 9.1 で実行しました。サンプルのファイルは Python 3.11.15(Pillow 12.2.0)・gcc 13.3.0・javac 21.0.10・Zip 3.0 で作り、壊れ方は Pillow・ImageMagick 6.9.12-98・UnZip 6.00 で確かめました。各エディタの機能・設定名・対応 OS は、VS Code Hex Editor の GitHub と Marketplace、HxD・Hex Fiend・ImHex・Okteta・GHex の公式ページ、窓の杜、PowerShell の Microsoft Learn で、ファイル形式は PNG・ZIP・ELF・PE・Unicode の仕様書で確かめました(確認日 2026年10月23日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「バイナリエディタとは|使い方・おすすめとxxdで読む実例・戻し方」
バイナリエディタとは(テキストエディタとの違い)
この節では、バイナリエディタが何をするソフトで、メモ帳などのテキストエディタと何が違うのかが分かります。
バイナリエディタ(binary editor)は、ファイルを「文字」ではなく「バイトの並び」として表示・編集するソフトです。 1バイトを16進数2桁(00〜FF)で見せるので、英語では hex editor(ヘックスエディタ、16進エディタ)とも呼びます。日本語では「バイナリーエディター」と書くこともあります。
コンピューターのファイルは、テキストでも画像でも、すべて 0〜255 の数が並んだものです。違いは「その数をどう解釈するか」だけです。
テキストエディタ(メモ帳・VS Code の通常の画面)
バイトを文字コード(UTF-8 など)で文字に直して見せる
文字にならないバイトは「?」や「�」に置き換わる
保存するときに文字コード・改行コードで書き直す
バイナリエディタ
バイトの値を16進数のまま見せる。解釈しない
文字にならないバイトも、値がそのまま分かる
変えたバイト以外は1ビットも変えずに保存する
テキストファイルとバイナリファイル
テキストファイルは、文字コードで文字にできるバイトだけでできたファイルです。 .txt・.csv・.html・.java などがあたります。それ以外(画像・圧縮ファイル・実行ファイル・Word の .docx など)をまとめてバイナリファイルと呼びます。拡張子は名前の一部にすぎず、中身の形式は先頭のバイトを見ると分かります(後の節)。
バイナリエディタでできること
1中身を見る
拡張子が無い・開けないファイルが何の形式か、先頭のバイトで調べる。
2文字コードを調べる
BOM の有無、改行が CRLF か LF か、UTF-8 か Shift_JIS かをバイトで確かめる。
3書き換える
特定の位置のバイトを上書きする。テスト用の壊れたデータを作るときにも使う。
4比べる・探す
2つのファイルのどのバイトが違うか、ある値が何バイト目にあるかを調べる。
プログラマーは、ファイル形式を扱うプログラムの確認、文字化けの原因調べ、通信データやバイナリ形式の設定ファイルの確認などで使います。
16進数とバイトの見方(アドレス・16進・文字の3列)
この節では、バイナリエディタの画面の3つの列を、実際の表示で読めるようになります。
「あいA」と改行を UTF-8 で保存したファイルを、xxd(Linux・macOS で使えるコマンド)で表示しました。
$ printf 'あいA\n' > utf8.txt
$ xxd utf8.txt
00000000: e381 82e3 8184 410a ......A.
| 列 | 例 | 意味 |
|---|---|---|
| アドレス(オフセット) | 00000000 | その行の先頭が、ファイルの何バイト目か(0 から数える16進数) |
| 16進数 | e381 82e3 8184 410a | 1バイトを2桁で。xxd は2バイトずつ区切る |
| 文字(ASCII) | ......A. | ASCII の文字になるバイトだけ文字、それ以外は「.」 |
読み方のポイントは次の3つです。
- 16進数2桁が1バイトです。
e38182の3バイトが「あ」、41が「A」、0aが改行(LF)です。このファイルは8バイトあります。 - アドレスは16進数で、1行に16バイト並ぶのが標準です。 2行目のアドレスは 00000010(10進数で16)になります。
- 右の文字の列は、ASCII として読めるバイトだけを表示します。 日本語は複数バイトなので「.」になります。エディタによっては文字コードを切り替えると日本語が表示されます。
16進数1桁は2進数4桁(4ビット)にあたり、2桁でちょうど1バイト(8ビット)になります。0〜F の対応だけ覚えておくと、画面が読めます。
| 16進数 | 10進数 | 2進数 |
|---|---|---|
| 0 | 0 | 0000 |
| 1 | 1 | 0001 |
| 2 | 2 | 0010 |
| 3 | 3 | 0011 |
| 4 | 4 | 0100 |
| 5 | 5 | 0101 |
| 6 | 6 | 0110 |
| 7 | 7 | 0111 |
| 8 | 8 | 1000 |
| 9 | 9 | 1001 |
| A | 10 | 1010 |
| B | 11 | 1011 |
| C | 12 | 1100 |
| D | 13 | 1101 |
| E | 14 | 1110 |
| F | 15 | 1111 |
16進数の変換・計算のやり方と0〜255の全対応表は、関連記事「16進数とは|変換・計算のやり方と0〜255早見表を3言語で実演」で扱っています。
バイナリエディタのおすすめと選び方(Windows・Mac・Linux・VS Code)
この節では、OS ごとに使えるバイナリエディタと、目的に合わせた選び方が分かります。版・対応 OS は各公式ページで確かめた2026年10月23日時点の内容です。
| ソフト | OS | 料金 | 特徴(公式の記載) |
|---|---|---|---|
| VS Code の Hex Editor | Win・Mac・Linux | 無料 | Microsoft 製の拡張機能。版 1.11.1。Data Inspector・検索と置換・挿入モード |
| HxD | Windows | 無料(フリーウェア) | 版 2.5.0.0(2021年2月)。日本語版とポータブル版あり。ディスク・メモリの編集、チェックサム |
| ImHex | Win・Mac・Linux | 無料(GPLv2) | 版 1.38.1(2025年12月)。構造を書くパターン言語、データインスペクタ、逆アセンブラ |
| Hex Fiend | Mac | 無料(BSD-2-Clause) | 版 2.18.1。118GB のファイルで試験、2つのファイルの差分表示 |
| Okteta | Linux(KDE) | 無料 | 版 0.26.28(2026年9月)。構造定義での解析、16・10・8・2進表示 |
| GHex | Linux(GNOME) | 無料 | 版 50.3(Flathub)。16進と ASCII の2列で編集 |
| Binary Editor BZ | Windows | 無料 | 窓の杜の版 v1.9.8.7。構造体の色分け、1バイト1ドットの画像表示 |
ほかに、Windows では Stirling・FavBinEdit、Mac では iHex・0xED も、昔から紹介されることの多いフリーソフトです。窓の杜の記事(2014年)によると、FavBinEdit は 4GB を超えるファイルを開け、JIS・EUC・Unicode の各形式で表示できます。Binary Editor BZ の窓の杜の対応 OS 欄は Windows 95/98/NT/2000/XP で、新しい Windows で使うときは自分の環境で動作を確かめてから使います。
迷ったときの選び方(判断表)
| こんなとき | 選ぶもの | 理由 |
|---|---|---|
| 少し見たい・VS Code を使っている | VS Code の Hex Editor | 拡張を1つ入れるだけ。どの OS でも同じ操作 |
| Windows で大きなファイル・ディスクを見る | HxD | ファイルの大きさに関係なく開け、ディスクの生データも読める |
| Mac で大きなファイル・差分を見る | Hex Fiend | メモリに全部読み込まない作り。File > Compare で差分 |
| ファイル形式を構造ごとに読み解く | ImHex・Okteta | 構造体の定義で、バイトに名前と型を付けて表示できる |
| サーバーで見るだけ・インストールできない | xxd・hexdump・od | Linux・macOS に最初からある(Windows は Format-Hex) |
| 決まった位置を何度も直す | xxd -r・Python | 手順をスクリプトにでき、同じ結果をくり返せる |
ブラウザで動くバイナリエディタもあります。ファイルを手元だけで処理するか、サーバーに送るかはサービスごとに違うので、社外に出せないファイルは手元のソフトで開きます。
VS Code の Hex Editor 拡張の使い方
この節では、VS Code でバイナリファイルを開いて、見る・直す・保存するまでの操作が分かります。
Hex Editor は Microsoft が出している拡張機能で、拡張機能の ID は ms-vscode.hexeditor です(Marketplace のインストール数は 7,474,737)。GitHub の README と package.json で、操作と設定の名前を確かめました。
拡張機能を入れる
拡張機能ビューで「hex editor」と検索し、発行者が Microsoft の「Hex Editor」を入れる。
Hex Editor で開く
エクスプローラーでファイルを右クリック →「Open With」→「Hex Editor」。開いているファイルなら、コマンドパレット(F1)の「Reopen With」→「Hex Editor」。
見る・移動する
左がアドレス、中央が16進数、右が Decoded Text。Ctrl+G(Go To Offset)で決まった位置へ飛ぶ。右側の Data Inspector に、選んだバイトを整数・浮動小数点数などとして読んだ値が出る。
書き換える
16進数の欄で値を打つと上書きになる。Insert キー(Switch Edit Mode)で挿入モードに切り替わる。Ctrl+Z で元に戻せる。
保存する
Ctrl+S で保存する。保存する前に、元のファイルのコピーを別名で残しておく。
settings.json で変えられる主な設定です(package.json の既定値)。
| 設定名 | 既定値 | 意味 |
|---|---|---|
| hexeditor.columnWidth | 16 | 1行に並べるバイト数(1〜512) |
| hexeditor.showDecodedText | true | 右側の文字の列を出すか |
| hexeditor.defaultEndianness | little | Data Inspector で数値を読むときのバイト順 |
| hexeditor.inspectorType | aside | Data Inspector の場所(aside・hover・sidebar) |
| hexeditor.maxFileSize | 10 | これより大きい(MB)ファイルは開く前に警告する |
| hexeditor.copyType | Hex Octets | Copy As...(Ctrl+Alt+C)の既定の形式(C・Java・Base64 など) |
特定の拡張子を、いつも Hex Editor で開くこともできます。
{
"workbench.editorAssociations": {
"*.bin": "hexEditor.hexedit"
}
}
VS Code のインストールと日本語化は、関連記事「VSCode日本語化とインストール手順|Win/Mac/Linuxと直し方」で扱っています。
コマンドでファイルの中身を見る(xxd・hexdump・od・Format-Hex)
この節では、ソフトを入れずに、ターミナルでバイナリを表示する方法と、コマンドごとの違いが分かります。
Linux と macOS では xxd・hexdump・od、Windows では PowerShell の Format-Hex が使えます。同じ PNG ファイル(2×2 ピクセル、79 バイト)を3つのコマンドで表示しました。
$ xxd red.png
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 0002 0000 0002 0802 0000 00fd d49a ................
00000020: 7300 0000 1649 4441 5478 9c63 fccf c0c0 s....IDATx.c....
00000030: c0c0 c0c4 c0c0 c0c0 c000 000d 1d01 036a ...............j
00000040: c29b e900 0000 0049 454e 44ae 4260 82 .......IEND.B`.
$ hexdump -C red.png
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 00 02 00 00 00 02 08 02 00 00 00 fd d4 9a |................|
00000020 73 00 00 00 16 49 44 41 54 78 9c 63 fc cf c0 c0 |s....IDATx.c....|
00000030 c0 c0 c0 c4 c0 c0 c0 c0 c0 00 00 0d 1d 01 03 6a |...............j|
00000040 c2 9b e9 00 00 00 00 49 45 4e 44 ae 42 60 82 |.......IEND.B`.|
0000004f
$ od -A x -t x1z red.png
000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 >.PNG........IHDR<
000010 00 00 00 02 00 00 00 02 08 02 00 00 00 fd d4 9a >................<
(以下略)
3つとも中身は同じで、区切り方と文字の列の囲み方だけが違います。ただし、hexdump と od をオプションなしで使うと、2バイトずつ入れ替わって表示されます。
$ hexdump red.png | head -1
0000000 5089 474e 0a0d 0a1a 0000 0d00 4849 5244
$ od -x red.png | head -1
0000000 5089 474e 0a0d 0a1a 0000 0d00 4849 5244
89 50 が 5089 になっています。これは2バイトを1つの数としてリトルエンディアン(後の節)で読んだ結果で、ファイルの並びとは逆です。1バイトずつ見るときは hexdump -C か od -t x1 を使います。
よく使うオプションの早見表
| やりたいこと | xxd | hexdump・od |
|---|---|---|
| 1バイトずつ・文字も表示 | xxd file | hexdump -C file / od -A x -t x1z file |
| 先頭の 64 バイトだけ | xxd -l 64 file | hexdump -C -n 64 file |
| 0x10 バイト目から | xxd -s 0x10 file | hexdump -C -s 0x10 file |
| 区切らず16進数だけ | xxd -p file | od -An -tx1 file |
| 大文字で・1バイトずつ区切る | xxd -u -g 1 file | ― |
| 2進数で表示 | xxd -b file | ― |
| C 言語の配列にする | xxd -i file | ― |
| 16進数からバイナリに戻す | xxd -r / xxd -r -p | ― |
xxd は vim に付いてくるコマンドで、Ubuntu では xxd パッケージ(sudo apt install xxd)として入ります。xxd -b -l 4 red.png は 10001001 01010000 01001110 01000111、xxd -i は unsigned char hello_txt[] = { 0x48, 0x65, ... }; のような C のコードを出しました。
Windows の PowerShell では、Format-Hex -Path .\red.png -Count 48 のように使います。Microsoft Learn によると、-Count(表示するバイト数)と -Offset(読み飛ばすバイト数)は PowerShell 6.2 で入ったパラメーターで、出力は「Offset・Bytes・Ascii」の3列です。
大きなファイルはテキストにすると4倍以上になる
50MB の乱数ファイルを、それぞれのコマンドで全部テキストに変換した時間です(2コアのマシン)。
1バイトが「2桁+空白+文字」になるので、テキストにすると元の4倍以上の大きさになります。 大きなファイルは -s と -l で見たい所だけを出すか、全部を読み込まない作りのエディタ(HxD・Hex Fiend など)で開きます。
hexyl・hexedit(ターミナルで動くビューアとエディタ)
hexyl は、バイトの種類(NULL・ASCII・それ以外)で色を分けて表示するビューアです(Ubuntu の apt で入ります)。色を消して表示すると次のようになります。
$ hexyl --color=never -n 32 red.png
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 89 50 4e 47 0d 0a 1a 0a ┊ 00 00 00 0d 49 48 44 52 │×PNG__•_┊000_IHDR│
│00000010│ 00 00 00 02 00 00 00 02 ┊ 08 02 00 00 00 fd d4 9a │000•000•┊••000×××│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
hexedit は、ターミナルの中で動くバイナリエディタです。hexedit ファイル名 で開き、16進数の欄で値を打つと上書きされ、Tab で文字の欄に移ります。Ctrl+X を押すと Save changes (Yes/No/Cancel) ? と聞かれ、y で保存、n で保存せずに終わりました。マニュアルによると、F2(Ctrl+W)で保存、Ctrl+C で保存せずに終了、Ctrl+G で位置へ移動、Ctrl+S で検索、Ctrl+U ですべての変更を取り消します。
ファイルの先頭で種類が分かる(マジックナンバー一覧)
この節では、ファイルの先頭の数バイト(マジックナンバー)で、拡張子に関係なく形式を見分ける方法が分かります。
多くのファイル形式は、先頭に決まったバイトを置きます。これをマジックナンバー(シグネチャ)と呼びます。手元で作った12個のファイルの先頭8バイトです。
$ for f in red.png red.jpg red.gif red.pdf hello.zip hello.txt.gz hello sample.exe H.class t.db utf8bom.txt utf16.txt; do printf '%-13s ' $f; xxd -l 8 $f | cut -c11-50; done
red.png 8950 4e47 0d0a 1a0a
red.jpg ffd8 ffe0 0010 4a46
red.gif 4749 4638 3761 0200
red.pdf 2550 4446 2d31 2e34
hello.zip 504b 0304 0a00 0000
hello.txt.gz 1f8b 0800 0000 0000
hello 7f45 4c46 0201 0100
sample.exe 4d5a 9000 0300 0000
H.class cafe babe 0000 0041
t.db 5351 4c69 7465 2066
utf8bom.txt efbb bfe3 8182 e381
utf16.txt fffe 4230 4430 4100
| 形式 | 先頭のバイト | 文字で読むと |
|---|---|---|
| PNG | 89 50 4E 47 0D 0A 1A 0A | .PNG と改行など |
| JPEG | FF D8 FF | ― |
| GIF | 47 49 46 38 37 61(または 39 61) | GIF87a・GIF89a |
| 25 50 44 46 2D | %PDF- | |
| ZIP(docx・xlsx・jar も) | 50 4B 03 04 | PK |
| gzip | 1F 8B | ― |
| ELF(Linux の実行ファイル) | 7F 45 4C 46 | .ELF |
| PE(Windows の exe・dll) | 4D 5A | MZ |
| Java の class | CA FE BA BE | ― |
| SQLite | 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 | SQLite format 3 |
| UTF-8(BOM付き) | EF BB BF | ― |
| UTF-16 LE(BOM付き) | FF FE | ― |
Linux の file コマンドは、このマジックナンバーを使って形式を判定します。拡張子を変えても、file の結果は変わりません。Word の .docx や Excel の .xlsx は中身が ZIP なので、先頭は PK です。
PNG の先頭を読む(ビッグエンディアン)
PNG の仕様書の「Rationale」は、先頭8バイトのそれぞれに役割があると説明しています。
| バイト | 役割(PNG 仕様書の説明) |
|---|---|
| 89 | ASCII でない値にして、テキストファイルと取り違えにくくする |
| 50 4E 47 | 形式の名前「PNG」 |
| 0D 0A | CR LF。改行コードを変える転送で壊れたことを見つける |
| 1A | Ctrl+Z。MS-DOS でファイルの表示を止める |
| 0A | LF。CR LF の逆の変換で壊れたことを見つける |
続く IHDR(画像の基本情報)を、上の xxd の出力から読むと次のとおりです。
| 位置 | バイト | 意味 |
|---|---|---|
| 0x08 | 00 00 00 0D | IHDR のデータの長さ = 13 |
| 0x0C | 49 48 44 52 | チャンクの名前「IHDR」 |
| 0x10 | 00 00 00 02 | 幅 = 2 ピクセル |
| 0x14 | 00 00 00 02 | 高さ = 2 ピクセル |
| 0x18 | 08 02 | ビット深度 8・色の型 2(RGB) |
| 0x1D | FD D4 9A 73 | CRC(チャンク名とデータから計算した検査値) |
PNG の仕様では、数値は上位のバイトが先に来る順(ビッグエンディアン)で書きます。00 00 00 02 はそのまま 2 と読みます。
ZIP の先頭を読む(リトルエンディアン)
$ xxd -l 48 hello.zip
00000000: 504b 0304 0a00 0000 0000 937d 575d 1635 PK.........}W].5
00000010: 9631 0600 0000 0600 0000 0900 0000 6865 .1............he
00000020: 6c6c 6f2e 7478 7448 656c 6c6f 0a50 4b01 llo.txtHello.PK.
| 位置 | バイト | 意味 |
|---|---|---|
| 0x00 | 50 4B 03 04 | ローカルファイルヘッダーの署名 0x04034b50 |
| 0x0E | 16 35 96 31 | CRC-32 = 0x31963516 |
| 0x12 | 06 00 00 00 | 圧縮後の大きさ = 6 バイト |
| 0x1A | 09 00 | ファイル名の長さ = 9(hello.txt) |
| 0x1E | 68 65 6C 6C 6F … | ファイル名 hello.txt、その後に中身 Hello |
ZIP の仕様書(PKWARE の APPNOTE)は、値をすべてリトルエンディアンで書くと決めています。署名の値 0x04034b50 を下位のバイトから並べると 50 4B 03 04(PK)になります。CRC の 16 35 96 31 も、逆から読んで 0x31963516 です。
実行ファイル(ELF・PE)の先頭を読む
gcc で作った Linux の実行ファイルの先頭と、readelf -h の結果です。
$ xxd -l 32 hello
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 3e00 0100 0000 8010 0000 0000 0000 ..>.............
$ readelf -h hello
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Entry point address: 0x1080
5バイト目の 02 が 64 ビット(ELFCLASS64)、6バイト目の 01 がリトルエンディアン(ELFDATA2LSB)です。0x18 バイト目からの 80 10 00 00 00 00 00 00 は、プログラムが始まる位置(エントリーポイント)で、逆から読んで 0x1080 です。readelf の表示と一致しました。
Windows の exe は先頭が MZ で、Microsoft Learn の PE 形式の説明によると、0x3C バイト目に「PE 署名の位置」が入っています。Python の setuptools に含まれる Windows 用の exe で確かめると、0x3C の 00 01 00 00 は 0x100 で、0x100 バイト目に PE\0\0 がありました。
テキストファイルを読む(BOM・改行コード・文字コードの見分け)
この節では、文字化けや「動かないスクリプト」の原因になる、BOM・改行コード・文字コードの違いをバイトで見分ける方法が分かります。
同じ「あいA」と改行を、保存のしかたを変えて6つのファイルにしました。
utf8.txt 00000000: e381 82e3 8184 410a ......A.
utf8bom.txt 00000000: efbb bfe3 8182 e381 8441 0a .........A.
crlf.txt 00000000: e381 82e3 8184 410d 0a ......A..
sjis.txt 00000000: 82a0 82a2 410a ....A.
eucjp.txt 00000000: a4a2 a4a4 410a ....A.
utf16.txt 00000000: fffe 4230 4430 4100 0a00 ..B0D0A...
| 見る所 | バイト | 分かること |
|---|---|---|
| 先頭が EF BB BF | efbb bf | UTF-8 の BOM 付き |
| 先頭が FF FE / FE FF | fffe | UTF-16 のリトル/ビッグエンディアン |
| 行の終わりが 0D 0A | 0d0a | 改行が CRLF(Windows 式) |
| 行の終わりが 0A だけ | 0a | 改行が LF(Linux・macOS 式) |
| 「あ」が E3 81 82 | e381 82 | UTF-8(日本語は1文字3バイトが多い) |
| 「あ」が 82 A0 | 82a0 | Shift_JIS(日本語は1文字2バイト) |
| 「あ」が A4 A2 | a4a2 | EUC-JP(日本語は1文字2バイト) |
Unicode の FAQ によると、UTF-8 は BOM があってもなくてもバイト順は同じで、BOM は「UTF-8 であることを示す目印」としてだけ使われます。BOM を想定していないプログラムもあります。
BOM と CRLF で実際に起きるエラー
BOM 付きや CRLF のシェルスクリプト・JSON を実行すると、次のエラーになりました。どれも、エディタの画面では見えない数バイトが原因です。
$ bash -c './crlf.sh' # 改行が CRLF のスクリプト
bash: line 1: ./crlf.sh: cannot execute: required file not found
$ ./crlf.sh # zsh から実行した場合
./crlf.sh: bad interpreter: /bin/bash^M: no such file or directory
$ bash bom.sh # 先頭に BOM があるスクリプト
bom.sh: line 1: #!/bin/bash: No such file or directory
$ python3 -c "import json; json.load(open('bom.json'))"
json.decoder.JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1 (char 0)
xxd で見ると、原因がすぐ分かります。
$ xxd -l 16 crlf.sh
00000000: 2321 2f62 696e 2f62 6173 680d 0a65 6368 #!/bin/bash..ech
$ xxd -l 8 bom.sh
00000000: efbb bf23 212f 6269 ...#!/bi
1行目の終わりに 0d(CR)があるので、OS は /bin/bash に CR が付いた名前のプログラムを探して失敗します。BOM 付きのほうは、先頭の #! の前に efbb bf があるので、1行目が命令として扱われません。直し方は、sed -i 's/\r$//' crlf.sh で CR を消す、sed -i '1s/^\xEF\xBB\xBF//' bom.json で BOM を消す、Python なら encoding='utf-8-sig' で読む、のどれかです。直した後に xxd で 0d や efbb bf が消えたことを確かめると確実です。CRLF のエラーの詳しい直し方は、関連記事「bad interpreter: ^Mの直し方|改行コードCRLF」で扱っています。
文字コードは「読めるか」だけでは決めきれない
Python で「先に読めた文字コード」を調べる小さな判定スクリプト(後の節の inspect.py)を作ると、EUC-JP のファイルが Shift_JIS と判定されました。
>>> open('eucjp.txt','rb').read().decode('shift_jis')
'、「、、A\n'
>>> open('eucjp.txt','rb').read().decode('euc_jp')
'あいA\n'
EUC-JP の a4 a2 は、Shift_JIS では半角カナの2文字として読めてしまいます。file コマンドも、このファイルを ISO-8859 text と表示しました。短いファイルは、エラーが出ないことだけでは文字コードを決められません。 決まった文字(「あ」なら UTF-8 は E3 81 82、Shift_JIS は 82 A0)がどのバイトになっているかを見て判断します。文字コードとバイトの関係は、関連記事「UnicodeとUTF-8の違いとは?UTF-16・サロゲートペアまで実行結果で理解」で詳しく扱っています。
エンディアン(リトルエンディアンとビッグエンディアン)
この節では、2バイト以上の数がファイルにどの順で並ぶのかと、バイナリエディタでの読み方が分かります。
エンディアンは、複数バイトの数をどの順に並べるかの決まりです。 0x12345678 という4バイトの数を、Python の struct で2通りに書き出しました。
import struct
n = 0x12345678
print("リトルエンディアン:", struct.pack("<I", n).hex(" "))
print("ビッグエンディアン:", struct.pack(">I", n).hex(" "))
リトルエンディアン: 78 56 34 12
ビッグエンディアン: 12 34 56 78
0x12345678 のファイル上の並び
どちらで読むかを間違えると、PNG の幅 2 は 33,554,432 に、ELF の 0x1080 は 0x8010000000000000 になった
同じバイトでも、読む順で値が大きく変わります。
ELF の entry 8バイトを LE で読む: 0x1080
同じ8バイトを BE で読む : 0x8010000000000000
PNG の幅 4バイトを BE で読む: 2 LE で読むと: 33554432
コマンドでも、数としてまとめて表示するときはエンディアンが関わります。
$ xxd le.bin # ファイルの並びのまま
00000000: 7856 3412 xV4.
$ xxd -e le.bin # 4バイトをリトルエンディアンの数として表示
00000000: 12345678 xV4.
$ od -A x -t x4 le.bin # CPU のバイト順(この環境は Little Endian)
000000 12345678
$ od -A x -t x4 --endian=big be.bin
000000 12345678
VS Code の Hex Editor の Data Inspector も、既定(hexeditor.defaultEndianness)はリトルエンディアンです。ビッグエンディアンの形式(PNG など)を読むときは、Data Inspector の切り替えで big を選びます。浮動小数点数をバイトで見る方法は、関連記事「浮動小数点数とは|仕組み・誤差・0.1+0.2の理由を4言語で実演」で扱っています。
バイナリを書き換えて元に戻す手順(xxd -r・vim・Python)
この節では、決まった位置のバイトを書き換え、確かめ、元に戻すまでを、コマンドで再現できる形で示します。例として、Hello と改行の6バイトのファイルの先頭 H(48)を J(4A)に変えます。
バックアップとハッシュ値を取る
元のファイルを別名でコピーし、sha256sum で値を控える。戻したときに同じ値になれば、1ビットも違わない。
書き換える位置と今の値を確かめる
xxd -s 位置 -l 長さ で表示し、変える前の値が思ったとおりかを見る。
上書きで書き換える
xxd -r のパッチ形式・vim・Python のどれかで、同じ長さのまま値だけを変える。
違いが1か所だけか確かめる
cmp -l で、変えたバイトだけが違うことを見る。ファイルの大きさが変わっていないかも見る。
元に戻して確かめる
バックアップを戻すか、逆の値で書き換え、ハッシュ値が手順1と同じになることを見る。
xxd で書き換える(2通り)
1つ目は、ファイル全体を16進数のテキストにして編集し、xxd -r でバイナリに戻す方法です。
$ cp hello.txt hello.txt.bak && sha256sum hello.txt
66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18 hello.txt
$ xxd hello.txt > hello.hex
$ cat hello.hex
00000000: 4865 6c6c 6f0a Hello.
$ sed -i 's/^00000000: 4865/00000000: 4a65/' hello.hex # 48 を 4a に
$ xxd -r hello.hex > hello.txt
$ xxd hello.txt
00000000: 4a65 6c6c 6f0a Jello.
2つ目は、「位置: 値」だけを書いたパッチを、既存のファイルに当てる方法です。xxd -r の出力先に既存のファイルを指定すると、ファイルを作り直さず、その位置だけを上書きします。
$ echo '00000000: 4d' | xxd -r - hello.txt
$ cat hello.txt
Mello
$ printf 'ABCDEFGH' > p.bin; echo '00000002: 7a7a' | xxd -r - p.bin; cat p.bin
ABzzEFGH
戻せたかは、バックアップと比べて確かめます。
$ cp hello.txt.bak hello.txt
$ cmp hello.txt hello.txt.bak && echo same
same
$ sha256sum hello.txt
66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18 hello.txt
区切りのない16進数だけの形(xxd -p)でも往復できます。xxd -p hello.txt は 48656c6c6f0a を出し、xxd -r -p で元のバイトに戻りました。
vim をバイナリエディタとして使う
vim では、:%!xxd で画面を16進数にし、編集してから :%!xxd -r で戻して保存します。必ず vim -b(バイナリモード)で開きます。 同じ操作を、画面を出さずに実行した結果です。
$ vim -b -es -c '%!xxd' -c 's/^00000000: 4865/00000000: 4a65/' -c '%!xxd -r' -c 'wq' v.txt
$ xxd v.txt
00000000: 4a65 6c6c 6f0a Jello.
-b を付けずに、2バイトのファイル(AB)を開いて同じ往復をすると、保存しただけで最後に改行(0a)が足されました。
$ vim -es -c '%!xxd' -c '%!xxd -r' -c 'wq' nb.bin; xxd nb.bin
00000000: 4142 0a AB.
$ vim -b -es -c '%!xxd' -c '%!xxd -r' -c 'wq' b.bin; xxd b.bin
00000000: 4142 AB
Python で書き換える(コピペ用の完成コード)
決まった位置を何度も直すなら、スクリプトにすると間違いが減ります。書き換える前の値が思ったとおりでなければ止める・バックアップを作る・ファイルを切り詰めない(r+b)の3つを入れています。
import hashlib, shutil, sys
def sha(path):
return hashlib.sha256(open(path, "rb").read()).hexdigest()[:16]
def patch(path, offset, old_hex, new_hex):
old, new = bytes.fromhex(old_hex), bytes.fromhex(new_hex)
if len(old) != len(new):
sys.exit("長さが違います(上書きだけを行い、挿入・削除はしません)")
with open(path, "rb") as f:
f.seek(offset)
cur = f.read(len(old))
if cur != old:
sys.exit(f"0x{offset:x} の値が {cur.hex(' ')} で、指定の {old.hex(' ')} と違うので中止します")
shutil.copy2(path, path + ".bak") # 先にバックアップ
before = sha(path)
with open(path, "r+b") as f: # r+b = 読み書き・切り詰めない
f.seek(offset)
f.write(new)
print(f"0x{offset:x}: {old.hex(' ')} -> {new.hex(' ')} sha256 {before} -> {sha(path)} backup: {path}.bak")
if __name__ == "__main__":
patch(sys.argv[1], int(sys.argv[2], 0), sys.argv[3], sys.argv[4])
$ python3 patch.py hello.txt 0 48 4a
0x0: 48 -> 4a sha256 66a045b452102c59 -> 963b7e7103f26641 backup: hello.txt.bak
$ python3 patch.py hello.txt 0 48 4b
0x0 の値が 4a で、指定の 48 と違うので中止します
$ python3 patch.py hello.txt 0 4a 48
0x0: 4a -> 48 sha256 963b7e7103f26641 -> 66a045b452102c59 backup: hello.txt.bak
最後に逆の値で書き換えると、ハッシュ値が最初の 66a045b452102c59 に戻りました。
表示だけなら、hexdump -C と同じ形で出す次のコードが使えます(Windows でも動きます)。
import sys
def hexview(path, start=0, length=None, width=16):
with open(path, "rb") as f:
f.seek(start)
data = f.read() if length is None else f.read(length)
for i in range(0, len(data), width):
row = data[i:i + width]
hx = " ".join(f"{b:02x}" for b in row)
txt = "".join(chr(b) if 0x20 <= b < 0x7f else "." for b in row)
print(f"{start + i:08x} {hx:<{width * 3}} |{txt}|")
if __name__ == "__main__":
path = sys.argv[1]
start = int(sys.argv[2], 0) if len(sys.argv) > 2 else 0
length = int(sys.argv[3], 0) if len(sys.argv) > 3 else None
hexview(path, start, length)
$ python3 hexview.py red.png 0 32
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 00 02 00 00 00 02 08 02 00 00 00 fd d4 9a |................|
ファイルの種類・BOM・改行コードをまとめて調べる
マジックナンバー・BOM・改行の数を、1行で表示するスクリプトです。
import sys
MAGIC = [ # 先頭のバイト列 → 種類
(b"\x89PNG\r\n\x1a\n", "PNG"),
(b"\xff\xd8\xff", "JPEG"),
(b"GIF87a", "GIF"), (b"GIF89a", "GIF"),
(b"%PDF-", "PDF"),
(b"PK\x03\x04", "ZIP(docx・xlsx・jar も)"),
(b"\x1f\x8b", "gzip"),
(b"\x7fELF", "ELF(Linux の実行ファイル)"),
(b"MZ", "PE(Windows の exe・dll)"),
(b"\xca\xfe\xba\xbe", "Java の class"),
(b"SQLite format 3\x00", "SQLite"),
]
BOM = [
(b"\xef\xbb\xbf", "UTF-8(BOM付き)"),
(b"\xff\xfe", "UTF-16 LE(BOM付き)"),
(b"\xfe\xff", "UTF-16 BE(BOM付き)"),
]
def guess_text(data):
for enc in ("utf-8", "shift_jis", "euc_jp"):
try:
data.decode(enc)
return enc
except UnicodeDecodeError:
pass
return "不明"
def inspect(path):
data = open(path, "rb").read()
head = data[:16]
kind = next((n for m, n in MAGIC if data.startswith(m)), None)
bom = next((n for m, n in BOM if data.startswith(m)), None)
if kind:
desc = kind
elif bom:
desc = bom
else:
desc = "テキスト? 先に読めた文字コード: " + guess_text(data)
crlf = data.count(b"\r\n")
lf = data.count(b"\n") - crlf
cr = data.count(b"\r") - crlf
eol = f"CRLF={crlf} LF={lf} CR={cr}" if not kind else "-"
print(f"{path:12} {len(data):6}B {head[:8].hex(' '):23} {desc} 改行: {eol}")
for p in sys.argv[1:]:
inspect(p)
$ python3 inspect.py red.png hello.zip hello utf8.txt utf8bom.txt crlf.txt sjis.txt eucjp.txt utf16.txt
red.png 79B 89 50 4e 47 0d 0a 1a 0a PNG 改行: -
hello.zip 122B 50 4b 03 04 0a 00 00 00 ZIP(docx・xlsx・jar も) 改行: -
hello 15960B 7f 45 4c 46 02 01 01 00 ELF(Linux の実行ファイル) 改行: -
utf8.txt 8B e3 81 82 e3 81 84 41 0a テキスト? 先に読めた文字コード: utf-8 改行: CRLF=0 LF=1 CR=0
utf8bom.txt 11B ef bb bf e3 81 82 e3 81 UTF-8(BOM付き) 改行: CRLF=0 LF=1 CR=0
crlf.txt 9B e3 81 82 e3 81 84 41 0d テキスト? 先に読めた文字コード: utf-8 改行: CRLF=1 LF=0 CR=0
sjis.txt 6B 82 a0 82 a2 41 0a テキスト? 先に読めた文字コード: shift_jis 改行: CRLF=0 LF=1 CR=0
eucjp.txt 6B a4 a2 a4 a4 41 0a テキスト? 先に読めた文字コード: shift_jis 改行: CRLF=0 LF=1 CR=0
utf16.txt 10B ff fe 42 30 44 30 41 00 UTF-16 LE(BOM付き) 改行: CRLF=0 LF=1 CR=0
EUC-JP のファイルが shift_jis と出るのは、前の節で見たとおり、短いファイルではどちらとしても読めてしまうためです。
バイナリファイルの比較と検索(cmp・diff・grep)
この節では、2つのバイナリのどこが違うか、ある値がファイルの何バイト目にあるかを調べる方法が分かります。
PNG の幅のバイトだけを 2 から 3 に変えたファイル(w3.png)と、元のファイルを比べました。
$ cmp red.png w3.png
red.png w3.png differ: char 20, line 3
$ cmp -l red.png w3.png
20 2 3
$ diff <(xxd red.png) <(xxd w3.png)
2c2
< 00000010: 0000 0002 0000 0002 0802 0000 00fd d49a ................
---
> 00000010: 0000 0003 0000 0002 0802 0000 00fd d49a ................
cmp -l は「何バイト目(1から数える10進数)・元の値・新しい値(8進数)」を、違うバイトの数だけ出します。20バイト目は、0 から数えるアドレスでは 0x13 です。xxd の結果を diff で比べると、16進数のまま行単位で違いが分かります。
決まったバイト列の位置は、grep の -obUaP で探せます(-o 一致部分だけ、-b 位置を出す、-a バイナリをテキストとして扱う)。
$ grep -obUaP "IEND" red.png
71:IEND
$ grep -obUaP "\x49\x48\x44\x52" red.png
12:IHDR
$ xxd -s 71 -l 8 red.png
00000047: 4945 4e44 ae42 6082 IEND.B`.
位置は10進数で出ます。71 は 16進数で 0x47 で、xxd の -s 71 で同じ所が表示されました。
バイナリエディタでよくある失敗と直し方(壊れる・保存形式)
この節では、ファイルが壊れるよくある原因を、実際に壊して確かめた結果と、防ぎ方が分かります。
失敗1:テキストエディタで開いて保存した
PNG を UTF-8 のテキストとして読み込み、そのまま保存したのと同じ処理を Python で行うと、79 バイトが 117 バイトになり、画像として開けなくなりました。
$ xxd -l 16 text_saved.png
00000000: efbf bd50 4e47 0d0a 1a0a 0000 000d 4948 ...PNG........IH
$ file text_saved.png
text_saved.png: data
先頭の 89 が UTF-8 として正しくないので、置き換え文字(U+FFFD、UTF-8 で ef bf bd)に変わっています。テキストエディタは「読めないバイト」を別の文字に置き換えて保存するので、元に戻せません。 バイナリはバイナリエディタで開きます。
失敗2:改行コードの変換をかけた
0a を 0d 0a に変える変換(Git の改行設定や、FTP の ASCII モードと同じ処理)をかけると、2 バイト増えて開けなくなりました。
$ xxd -l 16 crlf.png
00000000: 8950 4e47 0d0d 0a1a 0d0a 0000 000d 4948 .PNG..........IH
$ convert crlf.png out.bmp
convert-im6.q16: improper image header `crlf.png' @ error/png.c/ReadPNGImage/4195.
PNG の先頭の 0d 0a と 0a は、まさにこの変換を見つけるために置かれています。Git で画像が壊れるときの設定は、関連記事「Git改行コード設定|autocrlfと.gitattributesの違い」で扱っています。
失敗3:挿入してしまい、後ろの位置が全部ずれた
ZIP の中身 Hello の H を、上書きで J にした場合と、J を1バイト挿入した場合です。
同じ「J」でも、上書きと挿入で壊れ方が違う
バイナリの書き換えは、ふつう上書きで行う
$ unzip -t ow.zip # 1バイト上書き(H→J)
testing: hello.txt bad CRC 7c5e941d (should be 31963516)
At least one error was detected in ow.zip.
$ unzip -t ins.zip # 1バイト挿入
warning [ins.zip]: 1 extra byte at beginning or within zipfile
(attempting to process anyway)
file #1: bad zipfile offset (local header sig): 1
(attempting to re-compensate)
testing: hello.txt bad CRC 2ef2f636 (should be 31963516)
At least one error was detected in ins.zip.
失敗4:中身と合わない値に書き換えた(CRC・長さ)
PNG の幅を 2 から 3 に書き換えると、ImageMagick は CRC の誤りとして読み込みを止めました。CRC を計算し直しても、画像のデータは 2×2 の分しかないので、Pillow は image file is truncated で止まりました。
| 書き換え | 結果(原文) |
|---|---|
| 幅だけ 2→3 | convert-im6.q16: IHDR: CRC error |
| 幅を 2→3、CRC も計算し直す | OSError: image file is truncated (0 bytes not processed) |
| 元のファイル | 2×2 の画像として開けた |
多くのファイル形式は、長さ・位置・検査値で中身とつじつまを合わせています。 1か所を変えたら、関係する値も合わせて直す必要があります。形式の仕様書を読み、どの値が関係するかを確かめてから書き換えます。
失敗5:保存のしかたでファイルが変わった
| やったこと | 起きたこと | 防ぎ方 |
|---|---|---|
| vim を -b なしで開いて保存 | 最後に改行 0a が1バイト足された | vim -b で開く |
| dd に conv=notrunc を付けずに上書き | 書いた位置より後ろが消えた(8→4バイト) | dd … conv=notrunc |
| xxd -r の結果を > で新しいファイルに | 書いた位置より前が 00 で埋まった | 既存ファイルを出力先にする(パッチ) |
| xxd の右側の文字の列だけを直した | 何も変わらなかった(xxd -r は無視する) | 16進数の欄を直す |
| 16進数に奇数の桁・g などを書いた | エラーにならず、違う値になった | 書いた後に xxd で確かめる |
dd と xxd の実際の結果です。
$ printf 'ABCDEFGH' > d.bin; printf '\x7a' | dd of=d.bin bs=1 seek=3 conv=notrunc status=none; xxd d.bin
00000000: 4142 437a 4546 4748 ABCzEFGH
$ printf 'ABCDEFGH' > d2.bin; printf '\x7a' | dd of=d2.bin bs=1 seek=3 status=none; xxd d2.bin
00000000: 4142 437a ABCz
$ echo '00000002: 7a7a' | xxd -r > q.bin; xxd q.bin
00000000: 0000 7a7a ..zz
$ echo '00000000: 4g65' | xxd -r | xxd
00000000: 65 e
書き換える前のチェックリスト
- 1元のファイルのコピーを別名で残したハッシュ値(sha256sum)も控えると、戻せたかを1行で確かめられる
- 2書き換える位置と、今の値を確かめたアドレスが0から数える16進数か、1から数える10進数かに注意(cmp・grep は10進数)
- 3上書きモードになっているVS Code の Hex Editor は Insert キーで挿入モードに切り替わる
- 4数値のエンディアンを確かめたPNG はビッグ、ZIP・x86 の実行ファイルはリトル。逆に書くと全く違う値になる
- 5関係する長さ・検査値も直したPNG のチャンクの CRC、ZIP の CRC-32 など
- 6保存後に、大きさと違いの数を確かめたls -l で大きさ、cmp -l で違うバイトの数を見る
壊れたかもしれないときに確かめる順番
- 1大きさが変わっていないかls -l で元のファイルと比べる。増えていれば挿入か改行の変換、減っていれば切り詰め
- 2先頭のマジックナンバーが正しいかxxd -l 16 と file で見る。file が data と出たら先頭が壊れている
- 3どこが違うかバックアップと cmp -l で比べる。違いが変えた所だけなら、検査値か長さの不一致を疑う
- 4形式の検査コマンドで確かめるZIP は unzip -t、画像は convert や Pillow で開く。エラー文に壊れた場所が出る
よくある質問
Q. バイナリエディタとは簡単に言うと何ですか? A. ファイルの中身を、文字に直さずに1バイトずつ16進数(00〜FF)で表示し、編集できるソフトです。英語では hex editor(16進エディタ)と呼びます。画像や実行ファイルなど、テキストエディタでは読めないファイルの中身を見られます。
Q. バイナリエディタのフリーソフトでおすすめは? A. どの OS でも使えるのは VS Code の Hex Editor 拡張と ImHex です。Windows なら HxD(日本語版・ポータブル版あり)、Mac なら Hex Fiend、Linux なら GHex・Okteta が無料で使えます。見るだけなら、Linux と macOS は xxd、Windows は PowerShell の Format-Hex でも中身を確かめられます。
Q. Windows 11 で使えるバイナリエディタは?
A. VS Code の Hex Editor、HxD、ImHex(公式は Windows 10/11 を推奨)などがあります。HxD の公式ページの対応 OS 欄は Windows 10 までの表記です。インストールせずに見るだけなら、PowerShell の Format-Hex -Path ファイル -Count 64 が使えます。
Q. Mac のバイナリエディタは? A. Hex Fiend(オープンソース、版 2.18.1、macOS 10.14.6 以降)が代表的です。ほかに ImHex(macOS 15 以降)、VS Code の Hex Editor、iHex・0xED などがあります。ターミナルなら xxd・hexdump・od が使えます。
Q. VS Code でバイナリファイルを開くには? A. Microsoft の Hex Editor 拡張(ms-vscode.hexeditor)を入れ、ファイルを右クリック →「Open With」→「Hex Editor」で開きます。Ctrl+G で位置へ移動、Insert キーで上書きと挿入の切り替え、Ctrl+S で保存です(VS Code の節)。
Q. Linux でバイナリを編集するコマンドは?
A. 見るだけなら xxd・hexdump -C・od -A x -t x1z、書き換えるなら xxd -r(パッチ形式)・vim -b と :%!xxd・ターミナルで動く hexedit があります。Ubuntu では sudo apt install xxd や sudo apt install hexedit で入ります。
Q. バイナリエディタで日本語が表示されないのは? A. 右側の文字の列は、多くのエディタで ASCII だけを表示するためです。日本語は UTF-8 で1文字3バイト、Shift_JIS で2バイトなので「.」になります。文字コードを切り替えられるエディタ(Hex Fiend・Okteta など)で UTF-8 や Shift_JIS を選ぶと、日本語が表示されます。
Q. バイナリファイルをメモ帳で開いて保存するとどうなりますか? A. 文字として読めないバイトが置き換え文字などに変わり、ファイルが壊れます。PNG を UTF-8 のテキストとして保存し直すと、79 バイトが 117 バイトになり、画像として開けなくなりました。保存しなければ元のファイルは変わりません。
Q. バイナリエディタで書き換えたファイルを元に戻すには? A. 書き換える前のコピーがあれば、それを戻すのが確実です。コピーが無い場合は、変えた位置と元の値が分かっていれば、同じ位置を元の値で上書きします。戻した後は sha256sum や cmp で、元のファイルと同じになったことを確かめます。
Q. 大きなファイル(数GB)を開くには?
A. ファイルを全部メモリに読み込まない作りのエディタを使います。HxD は最大 8EB まで、Hex Fiend は 118GB のファイルで試験したと公式に書かれています。VS Code の Hex Editor は、hexeditor.maxFileSize(既定 10MB)を超えると開く前に警告を出します。コマンドなら xxd -s 位置 -l 長さ で一部だけを表示します。
Q. 拡張子が無いファイルの種類を調べるには?
A. 先頭の数バイト(マジックナンバー)を見ます。89 50 4E 47 なら PNG、50 4B 03 04 なら ZIP(docx・xlsx も)、25 50 44 46 なら PDF、7F 45 4C 46 なら Linux の実行ファイルです。Linux・macOS では file コマンドが同じ方法で判定します。
まとめ
- バイナリエディタは、ファイルを「位置・16進数・文字」の3列で、1バイトずつ見て直すソフト。16進数2桁が1バイト。
- おすすめは、どの OS でも VS Code の Hex Editor と ImHex、Windows は HxD、Mac は Hex Fiend、Linux は GHex・Okteta。見るだけなら xxd・hexdump -C・od・Format-Hex。
- ファイルの種類は先頭のマジックナンバーで分かる。PNG は 89 50 4E 47、ZIP は 50 4B 03 04、ELF は 7F 45 4C 46、exe は 4D 5A。
- テキストは、BOM(EF BB BF)・改行(0D 0A か 0A)・「あ」のバイトで文字コードを見分ける。CRLF と BOM は実際に bash と json のエラーになった。
- 2バイト以上の数はエンディアンに注意。PNG はビッグ、ZIP と x86 の実行ファイルはリトル。hexdump・od をオプションなしで使うと2バイトずつ入れ替わって見える。
- 書き換えは、バックアップ→位置と値の確認→上書き→cmp で確認→元に戻せることの確認、の順で行う。挿入・テキストとしての保存・改行の変換・検査値の不一致で、ファイルは壊れる。
参考・出典
確認日はいずれも 2026年10月23日です。
- Visual Studio Marketplace「Hex Editor」:https://marketplace.visualstudio.com/items?itemName=ms-vscode.hexeditor
- GitHub「microsoft/vscode-hexeditor」(README・CHANGELOG・package.json):https://github.com/microsoft/vscode-hexeditor
- mh-nexus「HxD - Freeware Hex Editor and Disk Editor」:https://mh-nexus.de/en/hxd/
- GitHub「HexFiend/HexFiend」:https://github.com/HexFiend/HexFiend
- Hex Fiend「Release Notes」:https://hexfiend.github.io/HexFiend/ReleaseNotes.html
- GitHub「WerWolv/ImHex」:https://github.com/WerWolv/ImHex
- KDE Applications「Okteta」:https://apps.kde.org/okteta/
- Flathub「GHex」:https://flathub.org/apps/org.gnome.GHex
- 窓の杜「Binary Editor BZ」:https://forest.watch.impress.co.jp/library/software/binaryeditbz/
- 窓の杜「シンプルながら十分な機能を備えるバイナリエディター「FavBinEdit」」:https://forest.watch.impress.co.jp/docs/review/633443.html
- Microsoft Learn「Format-Hex」:https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.utility/format-hex
- Microsoft Learn「PE 形式」:https://learn.microsoft.com/ja-jp/windows/win32/debug/pe-format
- W3C「Portable Network Graphics (PNG) Specification (Third Edition)」:https://www.w3.org/TR/png-3/
- libpng.org「PNG Specification: Rationale」(PNG file signature):http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html
- PKWARE「APPNOTE.TXT - .ZIP File Format Specification」:https://pkwaredownloads.blob.core.windows.net/pem/APPNOTE.txt
- Linux man-pages「elf(5)」:https://man7.org/linux/man-pages/man5/elf.5.html
- Unicode「FAQ - UTF-8, UTF-16, UTF-32 & BOM」:https://www.unicode.org/faq/utf_bom.html
- Arch Linux manual pages「hexedit(1)」:https://man.archlinux.org/man/hexedit.1.en
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「バイナリエディタとは|使い方・おすすめとxxdで読む実例・戻し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。