RFC 3629 - UTF-8, ISO 10646の変換形式
公開日: 2003年11月
ステータス: インターネット標準 (STD 63)
著者: F. Yergeau (Alis Technologies)
廃止: RFC 2279
カテゴリ: Standards Track
概要 (Abstract)
ISO/IEC 10646-1は、世界中のほとんどの書記体系を包含する、Universal Character Set (UCS) と呼ばれる大規模な文字セットを定義しています。しかし、当初提案されたUCSのエンコーディングは、多くの現在のアプリケーションやプロトコルと互換性がありませんでした。これがUTF-8の開発につながり、本メモの主題となっています。UTF-8は、完全なUS-ASCII範囲を保持する特性を持ち、US-ASCII値に依存しながらも他の値に対して透過的なファイルシステム、パーサー、その他のソフトウェアとの互換性を提供します。本メモはRFC 2279を廃止し、置き換えるものです。
本メモの位置付け (Status of this Memo)
本文書は、インターネットコミュニティに対するインターネット標準トラックプロトコルを規定し、改善のための議論と提案を求めるものです。本プロトコルの標準化状態および地位については、「Internet Official Protocol Standards」(STD 1) の最新版を参照してください。本メモの配布は無制限です。
著作権表示 (Copyright Notice)
Copyright (C) The Internet Society (2003). All Rights Reserved.
目次 (Table of Contents)
主要セクション
- 1. Introduction (はじめに)
- 2. Notational conventions (表記規則)
- 3. UTF-8 definition (UTF-8定義)
- 4. Syntax of UTF-8 Byte Sequences (UTF-8バイトシーケンスの構文)
- 5. Versions of the standards (標準のバージョン)
- 6. Byte order mark (BOM) (バイトオーダーマーク)
- 7. Examples (例)
- 8. MIME registration (MIME登録)
- 9. IANA Considerations (IANAに関する考慮事項)
- 10. Security Considerations (セキュリティに関する考慮事項)
- 11. Acknowledgements (謝辞)
- 12. Changes from RFC 2279 (RFC 2279からの変更点)
- 13. Normative References (規範的参考文献)
- 14. Informative References (参考情報)
なぜUTF-8が重要なのか?
UTF-8は現代のインターネットの標準文字エンコーディングです。ほぼすべての現代のWebアプリケーション、API、データ形式がUTF-8を使用しています。
主な利点
| 特徴 | 説明 | 重要度 |
|---|---|---|
| ASCII互換 | ASCII文字は同じようにエンコードされる | ⭐⭐⭐⭐⭐ |
| バイトオーダーの問題なし | エンディアンの問題がない | ⭐⭐⭐⭐⭐ |
| 自己同期 | 任意の位置からデコード可能 | ⭐⭐⭐⭐ |
| 空間効率 | 英語1バイト、中国語3バイト | ⭐⭐⭐⭐ |
| ユニバーサルサポート | すべてのUnicode文字をサポート | ⭐⭐⭐⭐⭐ |
UTF-8エンコーディング規則クイックリファレンス
エンコーディングテーブル
Unicode範囲 バイト数 UTF-8バイトパターン
─────────────────────────────────────────────
U+0000 - U+007F 1 0xxxxxxx
U+0080 - U+07FF 2 110xxxxx 10xxxxxx
U+0800 - U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
U+10000 - U+10FFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
文字範囲カバレッジ
1バイト (ASCII):
- ラテン文字、数字、基本的な句読点
- 制御文字
- 範囲: U+0000 - U+007F
2バイト:
- ラテン拡張
- ギリシャ文字、キリル文字、アラビア文字、ヘブライ文字
- 範囲: U+0080 - U+07FF
3バイト:
- CJK文字(中国語、日本語、韓国語)
- その他のほとんどの文字体系
- 範囲: U+0800 - U+FFFF
4バイト:
- 絵文字
- 歴史的文字、稀な漢字
- 範囲: U+10000 - U+10FFFF
エンコーディングの例
ASCII文字
文字: 'A'
Unicode: U+0041
2進数: 0100 0001
UTF-8: 0x41
バイト数: 1
エンコーディングプロセス:
U+0041 < U+007F → 1バイトテンプレートを使用
0xxxxxxx → 01000001 → 0x41
中国語文字
文字: '你'
Unicode: U+4F60
2進数: 0100 1111 0110 0000
UTF-8: 0xE4 0xBD 0xA0
バイト数: 3
エンコーディングプロセス:
U+4F60はU+0800-U+FFFF範囲 → 3バイトテンプレートを使用
1110xxxx 10xxxxxx 10xxxxxx
↓ ↓ ↓
0100 111101 100000
↓ ↓ ↓
11100100 10111101 10100000
0xE4 0xBD 0xA0
絵文字
文字: '😀'
Unicode: U+1F600
2進数: 0001 1111 0110 0000 0000 0000
UTF-8: 0xF0 0x9F 0x98 0x80
バイト数: 4
エンコーディングプロセス:
U+1F600はU+10000-U+10FFFF範囲 → 4バイトテンプレートを使用
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
↓ ↓ ↓ ↓
000011 111101 100000 000000
↓ ↓ ↓ ↓
11110000 10011111 10011000 10000000
0xF0 0x9F 0x98 0x80
UTF-8の独自の特徴
1. ASCII互換性
ASCIIファイル = 有効なUTF-8ファイル
例:
Hello World (ASCII)
同時に有効なUTF-8でもある
理由:
ASCIIは7ビット (0xxxxxxx) を使用
UTF-8の1バイト形式はASCII
2. 自己同期 (Self-Synchronizing)
UTF-8バイトストリーム:
... E4 BD A0 E5 A5 BD ...
你 好
任意の位置から開始:
- 先頭バイト (1110xxxx または 110xxxxx または 11110xxx) が文字の開始を示す
- 後続バイト (10xxxxxx) は先頭バイトと誤認されない
例:
E4 BD A0 E5 A5 BD
↑ ↑
ここから開始すると後続バイトと識別できる
ここから開始すると新しい文字と識別できる
3. バイトオーダーの問題なし
UTF-16はBOMが必要:
FE FF ... (Big Endian)
FF FE ... (Little Endian)
UTF-8は不要:
バイトオーダーは固定、高位から低位へ
バイトオーダーを示すBOMは不要
一般的なアプリケーション
Web開発
<!-- HTMLファイル -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>UTF-8の例</title>
</head>
<body>
<p>你好,世界! Hello, World! 😀</p>
</body>
</html>
HTTPプロトコル
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
<!DOCTYPE html>...
JSONデータ
{
"name": "張三",
"message": "Hello 世界",
"emoji": "😀"
}
データベース
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
セキュリティ考慮事項のハイライト
⚠️ 非最短形式攻撃
禁止される過長エンコーディング:
正しい: 'A' → 0x41 (1バイト)
誤り: 'A' → 0xC0 0x81 (2バイト、過長)
'A' → 0xE0 0x80 0x81 (3バイト、過長)
危険性:
過長エンコーディングはセキュリティチェックをバイパスする可能性がある
例: パストラバーサル "../" の過長エンコーディング
⚠️ 無効なシーケンス
拒否すべきもの:
- 孤立した後続バイト (10xxxxxx)
- Unicode範囲を超えるもの (>U+10FFFF)
- UTF-16サロゲートペア (U+D800-U+DFFF)
- 切り詰められたマルチバイトシーケンス
プログラミング言語のサポート
Python
# エンコーディング
s = "你好世界"
b = s.encode('utf-8') # bytesオブジェクト
# デコーディング
s = b.decode('utf-8') # strオブジェクト
# ファイル操作
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
JavaScript
// エンコーディング
const str = "你好世界";
const encoder = new TextEncoder();
const bytes = encoder.encode(str); // Uint8Array
// デコーディング
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(bytes); // string
Java
// エンコーディング
String str = "你好世界";
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
// デコーディング
String decoded = new String(bytes, StandardCharsets.UTF_8);
// ファイル操作
Files.readString(path, StandardCharsets.UTF_8);
Go
// Goの文字列はネイティブでUTF-8
s := "你好世界"
// バイトスライスに変換
b := []byte(s)
// バイトスライスから変換
s = string(b)
パフォーマンス特性
空間効率の比較
| テキストタイプ | UTF-8 | UTF-16 | UTF-32 |
|---|---|---|---|
| 英語 | 1バイト | 2バイト | 4バイト |
| 中国語 | 3バイト | 2バイト | 4バイト |
| 絵文字 | 4バイト | 4バイト | 4バイト |
英語中心のテキスト: UTF-8が最適
CJK中心のテキスト: UTF-16がわずかに優れている
混合テキスト: UTF-8が通常最適
関連リソース (Related Resources)
- 公式テキスト: RFC 3629 (TXT)
- 公式ページ: RFC 3629 DataTracker
- 標準: STD 63
- 廃止: RFC 2279
- Unicode標準: Unicode.org
- ISO 10646: ISO/IEC 10646
クイック診断ツール
UTF-8エンコーディングの識別
def is_utf8(data):
"""データが有効なUTF-8かどうかを検出"""
try:
data.decode('utf-8')
return True
except UnicodeDecodeError:
return False
エンコーディング問題の修正
# よくある問題: 二重エンコーディング
# 元: "你好"
# 誤った表示: "ä½ å¥½"
# 修正方法:
text = "ä½ å¥½"
fixed = text.encode('latin1').decode('utf-8')
# 結果: "你好"
重要な注意: UTF-8は現代のインターネットのデフォルト標準です。常にUTF-8エンコーディングを使用し、GBK、ISO-8859-1、Windows-1252などのレガシーエンコーディングは避けてください。すべての新しいプロジェクトは、UTF-8を唯一の文字エンコーディングとして使用すべきです。