Slide 1

Slide 1 text

Unicodeと符号化形式 2021/07/26 Tadahisa Kamijo

Slide 2

Slide 2 text

Goal Unicode, UTF-8, UTF-16の違いを理解 プログラミング言語ごとの文字コードの扱いを理解

Slide 3

Slide 3 text

Before Unicode アメリカ: ASCII 西ヨーロッパ: Laten-1 日本: JIS X 0208 (Shift JIS, EUC-JP) IBM,NEC PC98が勝手に拡張した文字を統合→CP932(Windows-31J) 中国: GB 2312-80 (EUC-CN) 後のGB 18030が国家規格として採用・中国で対応が必須に 台湾: CCCII (EUC-CCCII-FT) 他にBigFive,CNS 11643等も存在 韓国: KS X 1001 (EUC-KR) 北朝鮮: KPS 9566 (EUC-KP) ベトナム: TCVN (EUC-VN) 1980年代に言語/ベンダによって異なる文字コードが定義され普及した

Slide 4

Slide 4 text

After Unicode 1991年に制定された文字コード 各国・各社の文字コードを統合 Xerox,Apple,IBM,Sun,HP ,JustSystem, etc... 最大約111万種の文字を定義可能

Slide 5

Slide 5 text

文字コードの大まかな種類 符号化文字集合 / CCS (Coded Character Set) 文字の集合に番号を振ったもの JIS X 0208 ("桜"は"26区89点") Unicode ("桜"は"U+685C") 文字符号化方式 / CES (Coded Encoding Scheme) コンピュータ内での表現方法 Shift JIS, EUC-JP UTF-8, UTF-16 https://www.asahi-net.or.jp/~ax2s-kmtn/ref/jisx0208.html https://unicode-table.com/en/685C/

Slide 6

Slide 6 text

UCS-2, UCS-4 初期バージョンのUnicodeで定義された符号化文字集合 Unicode 1.0.1, ISO/IEC 10646-1 そのまま文字符号化方式としても利用されていた

Slide 7

Slide 7 text

UCS-4 (Universal multi-octet Character Set 4) 1文字を31bitで表現 128群(group), 256面(plane), 256区(row), 256点(cell) で20億種 UCS-2 (Universal multi-octet Character Set 2) 1文字を16bitで表現 0群(group), 0面(plane) の65,535種 一般的に利用される文字はUCS-2にほぼ収録 歴史 当初UnicodeはUCS-2にすべての文字を収録する予定だったが、文字数の限 界が有りUCS-4に一般的でない文字を収録 UCS-2で収録された文字はBMP(Basic Multilingual Plane / 基本多言語面)と 呼ばれるように

Slide 8

Slide 8 text

UTF-16 UCS-2の置き換えとして定義 基本的には16bitで表現 UCS-2(BMP)に無くUCS-4に収録されている文字 U+10000 ~ U+10FFFF を 「サロゲートペア」として32bitで表現 UTF-16の符号化 スカラ値 | UTF-16 | 備考 -------------------------- | ----------------------------------- | --------- xxxxxxxx xxxxxxxx | xxxxxxxx xxxxxxxx | BMPはそのまま表現 000uuuuu xxxxxxxx xxxxxxxx | 110110ww wwxxxxxx 110111xx xxxxxxxx | wwww = uuuuu - 1 BMPで表現できず連続した16bit符号2つで表されるペアをサロゲートペアと呼ぶ

Slide 9

Slide 9 text

UTF-8 UCS-2(UTF-16)はAsciiコードとの互換性がない 英数字もすべて16bitで表現される Asciiコード互換の文字符号化方式としてUTF-8が定義された 当初はPlan9向けにベル研究所で考案された https://oraccha.hatenadiary.org/entry/20081004/1223124803 Asciiコードで利用されていない 0x80 ~ 0xFF の範囲を利用 最初のビットでバイト数を表現 110 2byte 1110 3byte 11110 4byte 1998年のrfc2279では最大6バイト,2003年のrfc3629では4バイト

Slide 10

Slide 10 text

https://ja.wikipedia.org/wiki/UTF-8 https://oku.edu.mie-u.ac.jp/~okumura/xhtml/utf8.html

Slide 11

Slide 11 text

UTF-32 UCS-4の符号をそのまま表現 利用可能な範囲は 0x00 ~ 0x10FFFF に制限されている

Slide 12

Slide 12 text

Unicode関連の用語 コードポイント 任意のUnicodeコードポイント 範囲は U+0 ~ U+10FFFF16 Surrogate Code Point UTF-16のサロゲートペアに使うコードポイント High-Surrogate Code Point: U+D800 ~ U+DBFF Low-Surrogate Code Point: U+DC00 ~ U+DFF Unicode スカラ値 一部の予約されたコードポイント以外の任意のUnicodeコードポイント U+1234 で表現 範囲は U+0 ~ U+D7FF16 U+E00016 ~ U+10FFFF16

Slide 13

Slide 13 text

亜種1: WTF-16 デコードできない可能性があるUTF-16をサポートするために定義 レガシーな環境向け サロゲートが対応していないUTF-16文字列が不正なUTF-16だと再定義され た 互換性のために昔のUTF-16をWTF-16として呼び、扱いを分ける 例えば ECMAScriptではString値を、UTF-16でデコードできない可能性のある16bit 整数配列で表現する Windowsのファイルシステムはパスを、UTF-16でデコードできない可能性の ある16bit整数配列で表現する

Slide 14

Slide 14 text

亜種2: WTF-8 不正でデコードできないWTF-16を強制的にUTF-8へ変換したバイト列 サロゲートが対応していなくてもそのまま結合する RustのWindowsでのOsStringはWTF-8で表現

Slide 15

Slide 15 text

亜種3: CESU-8 BMPの範囲はUTF-8と同一の表現 BMP外の文字列のエンコードが特殊 2つのUTF-16符号へエンコード ( → 0xD834 0xDD1E) 2つの符号をそれぞれ16bit整数のUnicodeのコードポイントとして解釈 (0xD834 0xDD1E→ U+D834 U+DD1E) UTF-8のエンコードを行う (3バイトのUTF-8が2つできる)

Slide 16

Slide 16 text

Oracleしか使っていないので理解する必要はないし、今となってはOracleも使わ ないほうが良いと言っている Oracle DatabaseではCESU-8を UTF-8 , 一般的なUTF-8を AL32UTF8 として 扱う MySQLも文字コードを utf8 と指定するとCESU-8が利用され、通常のUTF- 8を utf8mb4 として扱う アレな実装をOracleが使い始めて規格化してしまった https://docs.oracle.com/cd/F19136_01/nlspg/supporting-multilingual- databases-with-unicode.html#GUID-F3B0B4F7-B6D9-473D-840F- F98998F37981

Slide 17

Slide 17 text

その他、利用されていないUnicodeの符号化方式 UTF-7 UTF-16で表現したUnicodeをBase64で変換 7bit単位の制約があるメール等の環境向けに作られた ステートフルエンコーディングでXSS等の危険性が高く現在は利用されない https://gihyo.jp/admin/serial/01/charcode/0001 UTF-5 0-9,A-Vの32文字で表現する文字符号化方式 国際化ドメインでの利用を想定していたがPunycodeが採用されたので利用さ れていない UTF-9 UTF-8と比較してLaten-1が1バイト・主な漢字が2バイトで表現できる エイプリールフールのジョークRFCで定義

Slide 18

Slide 18 text

プログラミング言語とUnicode UTF-8のString型 Rust, Elixir, Julia, Swift 任意バイト列を文字列として扱う・解釈はライブラリに任される C, C++, Go, Rua, PHP , Zig 任意バイト列・エンコーディングを別に持つ Ruby (CSI正規化・デフォルトはUTF8) UTF-16のString型 16bit整数の配列: JavaScript, Java, C# Unicodeコードポイントの配列: Python

Slide 19

Slide 19 text

OSとUnicode Windows, MacOS UTF-16 NTFS, HFS+, UTF-16 UTF-16 ext4 UTF-8

Slide 20

Slide 20 text

参考資料1 .NETでの文字エンコード https://docs.microsoft.com/ja- jp/dotnet/standard/base-types/character-encoding-introduction JS Primer 文字列とUnicode https://jsprimer.net/basic/string-unicode/ utf8 rcf 1998 https://tools.ietf.org/html/rfc2279 2003 https://tools.ietf.org/html/rfc3629 What is the maximum number of bytes for a UTF-8 encoded character? https://stackoverflow.com/questions/9533258/what-is-the-maximum-number- of-bytes-for-a-utf-8-encoded-character 結合文字 (NFC,NFD) https://tama-san.com/combining_character_sequence/

Slide 21

Slide 21 text

参考資料2 wtf-8 https://simonsapin.github.io/wtf-8/ Unicodeとのつきあい方 https://www.jstage.jst.go.jp/article/konpyutariyoukyouiku/27/0/27_12/_article /-char/ja/ Unicodeとは? その歴史と進化、開発者向け基礎知識 https://www.buildinsider.net/language/csharpunicode/01 平成17年度漢籍担当職員講習会:文字コードとテキスト処理の歴史 http://kanji.zinbun.kyoto-u.ac.jp/~wittern/koushuukai/2005/index0.html 第2回 ユニコードについて ENGINEER COLUMN https://www.cresco- es.co.jp/column/unicode02/ UCSとUTF http://nomenclator.la.coocan.jp/unicode/ucs_utf.htm

Slide 22

Slide 22 text

参考資料3 Wikipedia UTF-16 https://ja.wikipedia.org/wiki/UTF-16 UTF-8 https://ja.wikipedia.org/wiki/UTF-8 UTF-32 https://ja.wikipedia.org/wiki/UTF-32 Unicode https://ja.wikipedia.org/wiki/Unicode WTF-8がrustで利用される https://twitter.com/qnighy/status/1038363399292313600