ISO-2022-JP
メールに使われているエンコーディング。それ以外ではみたことない。JISコードと呼ばれるらしいけど、個人的にはあんまり聞いたことないです。
ISO-2022-JPはISO-2022準拠のエンコーディングなので、複数のテーブルをエスケープシーケンスによって切り替えて使います。(ISO-2011-JPの説明は複雑なのでここでは省略します。このページをみてください。)簡単に言うと、特定の制御文字列を送ることで、「これからアルファベットを使います」「これから漢字を使います」と、状態を切り替えることで、たった7bitでアルファベット、数字、漢字をすべて表現することができるのです。
エスケープシーケンス
- これから送る文字はASCIIです: 0x0F, "ESC ( B", or "ESC ( J"
- これから送る文字は漢字です: "ESC $ @", or "ESC $ B"
- これから送る文字は補助漢字です: "ESC $ ( D"
- これから送る文字は半角カタカナです: 0x0E, or "ESC ( I"
なお、初期状態はASCIIです。なので、アルファベットと数字だけからなるメールにはエスケープシーケンスはいっさい含まれていません。(未確認ですがそのはず)
使用領域
7bitの領域をどのように使っているのか図示します。なお、制御文字が水色、ASCIIがオレンジ、漢字・補助漢字が緑、半角カタカナがグレーです。
ASCII使用時:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f |
漢字・補助漢字使用時:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f |
半角カタカナ使用時:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f |
Shift_JIS / Windows-31J など
依然としてクライアントサイドでは最も使われているエンコーディング。符号化文字集合が微妙に異なる親戚がたくさんいる。Shift_JISと呼ばれているものの多くは正確にはWindows-31Jであろう。
エスケープシーケンスを使わずASCII、漢字、半角カタカナを表現可能なのが便利だが、あるバイトを見たときに、それがASCIIなのか漢字を表現する2バイト目なのかを判別できない(場合がある)ので、波紋を呼んだりもした。
使用領域
1バイト目:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | a0 | b0 | c0 | d0 | e0 | f0 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 | 81 | 91 | a1 | b1 | c1 | d1 | e1 | f1 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 | 82 | 92 | a2 | b2 | c2 | d2 | e2 | f2 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 | 83 | 93 | a3 | b3 | c3 | d3 | e3 | f3 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 | 84 | 94 | a4 | b4 | c4 | d4 | e4 | f4 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 | 85 | 95 | a5 | b5 | c5 | d5 | e5 | f5 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 | 86 | 96 | a6 | b6 | c6 | d6 | e6 | f6 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 | 87 | 97 | a7 | b7 | c7 | d7 | e7 | f7 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 | 98 | a8 | b8 | c8 | d8 | e8 | f8 |
| a | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 | 89 | 99 | a9 | b9 | c9 | d9 | e9 | f9 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a | 8a | 9a | aa | ba | ca | da | ea | fa |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b | 8b | 9b | ab | bb | cb | db | eb | fb |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c | 8c | 9c | ac | bc | cc | dc | ec | fc |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d | 8d | 9d | ad | bd | cd | dd | ed | fd |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e | 8e | 9e | ae | be | ce | de | ee | fe |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f | 8f | 9f | af | bf | cf | df | ef | ff |
2バイト目:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | a0 | b0 | c0 | d0 | e0 | f0 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 | 81 | 91 | a1 | b1 | c1 | d1 | e1 | f1 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 | 82 | 92 | a2 | b2 | c2 | d2 | e2 | f2 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 | 83 | 93 | a3 | b3 | c3 | d3 | e3 | f3 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 | 84 | 94 | a4 | b4 | c4 | d4 | e4 | f4 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 | 85 | 95 | a5 | b5 | c5 | d5 | e5 | f5 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 | 86 | 96 | a6 | b6 | c6 | d6 | e6 | f6 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 | 87 | 97 | a7 | b7 | c7 | d7 | e7 | f7 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 | 98 | a8 | b8 | c8 | d8 | e8 | f8 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 | 89 | 99 | a9 | b9 | c9 | d9 | e9 | f9 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a | 8a | 9a | aa | ba | ca | da | ea | fa |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b | 8b | 9b | ab | bb | cb | db | eb | fb |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c | 8c | 9c | ac | bc | cc | dc | ec | fc |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d | 8d | 9d | ad | bd | cd | dd | ed | fd |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e | 8e | 9e | ae | be | ce | de | ee | fe |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f | 8f | 9f | af | bf | cf | df | ef | ff |
1バイト目のオレンジ(ASCII)と、2バイト目の緑(漢字)が一部重なっているのがわかりますね。
EUC-JP
Unix系で使われていた・・・ような気がするけど、あんまり覚えてない。これもISO-2022準拠のエンコーディングですが、エスケープシーケンスは使わず、シングルシフトを使います。(しつこいですが、ISO-2022についてはこのページをみてください。)
簡単に言うと、1バイト目が0x8Eだったら次の1バイトを半角カタカナとして認識する、1バイト目が0x8Fだったら次の2バイトを補助漢字として認識する、というルールです。
簡単に言うと、1バイト目が0x8Eだったら次の1バイトを半角カタカナとして認識する、1バイト目が0x8Fだったら次の2バイトを補助漢字として認識する、というルールです。
使用領域
Shift_JISと違って、空白が目立ちます。空間を贅沢に使ってる分、「漢字の2バイト目がアルファベットと間違えられる」というような問題は起こりません。デフォルト:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | a0 | b0 | c0 | d0 | e0 | f0 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 | 81 | 91 | a1 | b1 | c1 | d1 | e1 | f1 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 | 82 | 92 | a2 | b2 | c2 | d2 | e2 | f2 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 | 83 | 93 | a3 | b3 | c3 | d3 | e3 | f3 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 | 84 | 94 | a4 | b4 | c4 | d4 | e4 | f4 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 | 85 | 95 | a5 | b5 | c5 | d5 | e5 | f5 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 | 86 | 96 | a6 | b6 | c6 | d6 | e6 | f6 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 | 87 | 97 | a7 | b7 | c7 | d7 | e7 | f7 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 | 98 | a8 | b8 | c8 | d8 | e8 | f8 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 | 89 | 99 | a9 | b9 | c9 | d9 | e9 | f9 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a | 8a | 9a | aa | ba | ca | da | ea | fa |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b | 8b | 9b | ab | bb | cb | db | eb | fb |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c | 8c | 9c | ac | bc | cc | dc | ec | fc |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d | 8d | 9d | ad | bd | cd | dd | ed | fd |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e | 8e | 9e | ae | be | ce | de | ee | fe |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f | 8f | 9f | af | bf | cf | df | ef | ff |
1バイト目が0x8Eだったときの2バイト目:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | a0 | b0 | c0 | d0 | e0 | f0 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 | 81 | 91 | a1 | b1 | c1 | d1 | e1 | f1 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 | 82 | 92 | a2 | b2 | c2 | d2 | e2 | f2 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 | 83 | 93 | a3 | b3 | c3 | d3 | e3 | f3 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 | 84 | 94 | a4 | b4 | c4 | d4 | e4 | f4 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 | 85 | 95 | a5 | b5 | c5 | d5 | e5 | f5 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 | 86 | 96 | a6 | b6 | c6 | d6 | e6 | f6 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 | 87 | 97 | a7 | b7 | c7 | d7 | e7 | f7 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 | 98 | a8 | b8 | c8 | d8 | e8 | f8 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 | 89 | 99 | a9 | b9 | c9 | d9 | e9 | f9 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a | 8a | 9a | aa | ba | ca | da | ea | fa |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b | 8b | 9b | ab | bb | cb | db | eb | fb |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c | 8c | 9c | ac | bc | cc | dc | ec | fc |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d | 8d | 9d | ad | bd | cd | dd | ed | fd |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e | 8e | 9e | ae | be | ce | de | ee | fe |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f | 8f | 9f | af | bf | cf | df | ef | ff |
1バイト目が0x8Fだったときの2, 3バイト目:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | a0 | b0 | c0 | d0 | e0 | f0 |
| 1 | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71 | 81 | 91 | a1 | b1 | c1 | d1 | e1 | f1 |
| 2 | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72 | 82 | 92 | a2 | b2 | c2 | d2 | e2 | f2 |
| 3 | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73 | 83 | 93 | a3 | b3 | c3 | d3 | e3 | f3 |
| 4 | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74 | 84 | 94 | a4 | b4 | c4 | d4 | e4 | f4 |
| 5 | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75 | 85 | 95 | a5 | b5 | c5 | d5 | e5 | f5 |
| 6 | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76 | 86 | 96 | a6 | b6 | c6 | d6 | e6 | f6 |
| 7 | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77 | 87 | 97 | a7 | b7 | c7 | d7 | e7 | f7 |
| 8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 | 98 | a8 | b8 | c8 | d8 | e8 | f8 |
| 9 | 09 | 19 | 29 | 39 | 49 | 59 | 69 | 79 | 89 | 99 | a9 | b9 | c9 | d9 | e9 | f9 |
| a | 0a | 1a | 2a | 3a | 4a | 5a | 6a | 7a | 8a | 9a | aa | ba | ca | da | ea | fa |
| b | 0b | 1b | 2b | 3b | 4b | 5b | 6b | 7b | 8b | 9b | ab | bb | cb | db | eb | fb |
| c | 0c | 1c | 2c | 3c | 4c | 5c | 6c | 7c | 8c | 9c | ac | bc | cc | dc | ec | fc |
| d | 0d | 1d | 2d | 3d | 4d | 5d | 6d | 7d | 8d | 9d | ad | bd | cd | dd | ed | fd |
| e | 0e | 1e | 2e | 3e | 4e | 5e | 6e | 7e | 8e | 9e | ae | be | ce | de | ee | fe |
| f | 0f | 1f | 2f | 3f | 4f | 5f | 6f | 7f | 8f | 9f | af | bf | cf | df | ef | ff |
まとめ
意外にきれいな表になって嬉しい。Rubyを使ったのは半年ぶりだが、なんとなくそれっぽいコードを書けば動いてしまうのがRubyのすばらしいところだ。
余談: 元サイトの余談の引用
余談ですが、制御文字の中でDELだけ0x7Fなんていうところに飛ばされているのはなぜでしょうか? これは、データ入力媒体として紙テープを使っていたころの名残だといわれています。 紙テープでは、所定の位置に穴を空けてあるかどうかによって 2進数の1/0を区別します(SunOSのppt(6)を参照)。 1文字は7ビットですから、7つの位置の穴の有無で1文字を表します。 で、もし穴を空けるときにまちがってしまった場合、 穴をふさぐのは面倒ですので、そのまちがいを含む7ビット分全部の穴を空けて 「この字はまちがいだから削除ね」ということにしていました。 つまり、「削除」→「全ビット1」→「0x7F」というわけです。
Rubyソースコード
#!/usr/bin/ruby
ctrl = [0x00..0x1f, 0x7f..0x7f]
ascii = 0x0..0x0
#ascii = 0x20..0x7e
katakana = 0x0..0x0
#katakana = 0x21..0x5f
#katakana = 0xa1..0xdf
#katakana = 0xa1..0xdf
#kanji = []
#kanji = [0x21..0x7e]
#kanji = [0x81..0x9f, 0xe0..0xfc]
#kanji = [0x40..0x7e, 0x80..0xfc]
kanji = [0xa1..0xfe]
print <<EOS
<style type="text/css">
table.charcode {
border-collapse: collapse;
empty-cells: show;
}
table.charcode th,
table.charcode td {
width: 2em;
border: 1px solid gray;
text-align: center;
}
td.ctrl {
background-color: cyan;
}
td.ascii {
background-color: orange;
}
td.katakana {
background-color: lightgray;
}
td.kanji {
background-color: lightgreen;
}
</style>
EOS
print %Q!<table class="charcode">\n!
print "<tr><th></th>"
for b in 0x0..0xf
print "<th>#{sprintf("%x", b)}</th>"
end
print "</tr>"
for b0 in 0x0..0xf
print "<tr><th>#{sprintf("%x", b0)}</th>"
for b1 in 0x0..0xf
b = b1 * 0x10 + b0
if ctrl.any? { |r| r.include? b }
print %Q!<td class="ctrl">#{sprintf("%02x", b)}</td>!
elsif ascii.include? b
print %Q!<td class="ascii">#{sprintf("%02x", b)}</td>!
elsif katakana.include? b
print %Q!<td class="katakana">#{sprintf("%02x", b)}</td>!
elsif kanji.any? { |r| r.include? b }
print %Q!<td class="kanji">#{sprintf("%02x", b)}</td>!
else
print %Q!<td>#{sprintf("%02x", b)}</td>!
end
end
print "</tr>\n"
end
print "</table>\n"