プログラミングやWeb開発を行っていると、「文字コード」と「16進数」の関係を理解する必要が出てくる場面があります。
コンピューターは文字をそのまま扱えないため、すべての文字に数値(コードポイント)を割り当て、その数値を16進数で管理する仕組みが広く使われています。
文字化けの原因や、URLエンコード・Unicodeの仕組みを理解するためにも、16進数と文字コードの関係は欠かせない知識です。
本記事では、ASCIIコードと16進数の対応・Unicodeとの変換・日本語文字コードの仕組み・文字化けの原因まで、わかりやすく解説していきます。
ASCIIコードと16進数の対応関係
それではまず、ASCIIコードと16進数の対応関係について解説していきます。
ASCII(American Standard Code for Information Interchange)とは、英数字・記号・制御文字に0〜127の数値を割り当てた最も基本的な文字コード体系のことです。
コンピューターの世界では、この数値を16進数で表記することが一般的です。
たとえばアルファベット大文字「A」はASCIIコード65(10進数)であり、16進数では「41」と表されます。
主なASCII文字と16進数コードの対応
A=41 B=42 C=43 … Z=5A
a=61 b=62 c=63 … z=7A
0=30 1=31 2=32 … 9=39
スペース=20 !=21 @=40 #=23
大文字と小文字のコードの差が「20」(16進数)=32(10進数)であることに気づくと、文字コードの規則性が見えてきます。
この規則を利用して、大文字・小文字の変換をビット演算で実装するプログラムも存在するでしょう。
テキストを16進数に変換する仕組み
文字列を16進数のバイト列として表現することを「16進数ダンプ」または「ヘキサダンプ」と呼びます。
たとえば「Hello」という文字列は、ASCIIコードをもとに以下の16進数で表現されます。
「Hello」の16進数表現
H=48 e=65 l=6C l=6C o=6F
16進数ダンプ:48 65 6C 6C 6F
Pythonでの変換:「Hello」.encode().hex() → ‘48656c6c6f’
ヘキサエディタを使うと、テキストファイルや実行ファイルの内容を16進数のバイト列として直接確認・編集することができます。
デバッグや解析作業において非常に重要なスキルといえるでしょう。
16進数からテキストへの逆変換
16進数のバイト列から文字列への逆変換も、ASCIIテーブルを参照することで行えます。
Pythonでは「bytes.fromhex(‘48656c6c6f’).decode()」とすれば「Hello」という文字列が得られます。
この変換の仕組みを理解しておくことで、暗号化データや通信パケットのデコード作業にも対応できるようになるでしょう。
UnicodeとUTF-8での16進数表現
続いては、UnicodeとUTF-8における16進数表現を確認していきます。
現代のシステムではASCIIだけでは世界中の文字を表現できないため、Unicodeという拡張された文字コード体系が使われています。
Unicodeコードポイントと16進数
Unicodeでは、世界中のすべての文字に「U+XXXX」という形式のコードポイントを割り当てています。
この「XXXX」の部分が16進数であり、たとえば日本語の「あ」はU+3042、「日」はU+65E5と表されます。
Unicodeは現在100万文字以上を収録しており、絵文字・漢字・アラビア文字・ヒンディー文字など世界中の文字体系をカバーしています。
Pythonでは「ord(‘あ’)」で10進数コードポイントを、「hex(ord(‘あ’))」で16進数コードポイントを取得できるでしょう。
UTF-8エンコードと16進数の関係
UTF-8はUnicodeのコードポイントをバイト列に変換するエンコード方式であり、Webページやデータ交換の標準として広く使われています。
ASCII文字(U+0000〜U+007F)は1バイト(2桁の16進数)で表現でき、日本語などの多言語文字は3バイト(6桁の16進数)で表現されます。
| 文字 | Unicodeコードポイント | UTF-8(16進数) | バイト数 |
|---|---|---|---|
| A | U+0041 | 41 | 1バイト |
| é | U+00E9 | C3 A9 | 2バイト |
| あ | U+3042 | E3 81 82 | 3バイト |
| 😀 | U+1F600 | F0 9F 98 80 | 4バイト |
日本語の1文字が3バイト(6桁の16進数)で表されるため、ファイルサイズの計算やバッファサイズの設計においてバイト数を意識することが重要です。
文字化けの原因と16進数の関係
文字化けは、文字を書き込んだ際のエンコードと、読み込んだ際のエンコードが一致しないことで発生します。
たとえばShift-JISでエンコードされた日本語テキストをUTF-8として読み込もうとすると、バイト列の解釈が異なるため文字化けが生じます。
ヘキサダンプでバイト列を直接確認し、どのエンコードのパターンと一致するかを調べることで文字化けの原因を特定できるでしょう。
URLエンコードと16進数の仕組み
続いては、URLエンコード(パーセントエンコーディング)と16進数の仕組みを確認していきます。
WebシステムではURLに使用できない文字を16進数のバイト列で表現するURLエンコードが使われます。
パーセントエンコーディングの仕組み
URLエンコードでは、使用できない文字を「%XX」の形式(XXは16進数2桁)で表現します。
URLエンコードの例
スペース → %20
「あ」(UTF-8)→ %E3%81%82
「日本語」→ %E6%97%A5%E6%9C%AC%E8%AA%9E
WebブラウザのURLバーに日本語を入力すると、裏でこのようなパーセントエンコーディングが自動的に行われています。
APIのリクエストを作成する際や、フォームデータの送受信を実装する際にこの仕組みを理解していると、不具合の原因究明がスムーズに行えるでしょう。
Pythonでの文字コード・16進数変換
Pythonを使った実用的な変換例をまとめます。
Pythonでの文字コード変換例
文字→16進数:’あ’.encode(‘utf-8’).hex() → ‘e38182’
16進数→文字:bytes.fromhex(‘e38182’).decode(‘utf-8’) → ‘あ’
Unicodeコードポイント確認:hex(ord(‘あ’)) → ‘0x3042’
URLエンコード:urllib.parse.quote(‘日本語’) → ‘%E6%97%A5%E6%9C%AC%E8%AA%9E’
これらの変換操作を理解しておくことで、文字コード関連の不具合対応やデータ処理がスムーズに行えるでしょう。
まとめ
本記事では、ASCIIコードと16進数の対応・Unicodeの仕組み・UTF-8エンコード・文字化けの原因・URLエンコードまで幅広く解説してきました。
コンピューターの世界では文字はすべて数値(16進数)として管理されており、この仕組みを理解することがプログラミングやシステム開発の基礎となります。
文字化けはエンコードの不一致が原因であり、16進数レベルでバイト列を確認できると原因特定がスムーズになるでしょう。
ぜひ本記事を参考に、文字コードと16進数の関係をしっかりと理解してください。