• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Unicodeについて教えてgooでしつこくきいてみたよ♪
 

Unicodeについて教えてgooでしつこくきいてみたよ♪

on

  • 2,344 views

 

Statistics

Views

Total Views
2,344
Views on SlideShare
1,959
Embed Views
385

Actions

Likes
0
Downloads
2
Comments
3

7 Embeds 385

http://www.1000torque.com 355
http://blog.senbikiya.biz 18
https://twitter.com 6
https://si0.twimg.com 3
http://webcache.googleusercontent.com 1
http://localhost 1
http://senbiki.wordpress.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

13 of 3 previous next Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • この田中一生の不覚でござる。
    Are you sure you want to
    Your message goes here
    Processing…
  • しまったところどころ誤字がある。
    Are you sure you want to
    Your message goes here
    Processing…
  • ふむふむ 
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Unicodeについて教えてgooでしつこくきいてみたよ♪ Unicodeについて教えてgooでしつこくきいてみたよ♪ Presentation Transcript

    • 文字コードってなんじゃらほい? とくにUnicodeってなによ?
    • 文字コードの種類。文字コード => なんかいっぱいある。Shift-JIS とかEUC-JPとかUTF-8とかUTF-16とかUTF-32とか・・・・・。 あ!あとASCIIとか。
    • この本によると・・・・。
    • 文字コードとは?特定のユニークな文字(一文字分)と 特定のユニークなバイナリ列との 組み合わせらしい。 つまりマーキング。
    • 組み合わせ?例えば、【A】という文字をパソコンちゃんがディスプレイに出力するには【A】という文字を 知っている必要がある。 でもパソコンちゃんは頭の痛い子なので 【1】と【0】しか読めない・・・・・・。
    • しょうがないから【1】と【0】で。 Aという文字と 1と0の組み合わせを    紐付けるという作業をする。 それが文字コード。たぶん。Aは特定のユニークな1と0の並びに対応する。
    • 確認してみる。 value = Ap value .unpack( C* ) # => [65] ※unpack( C* )とは文字の値を 0∼255の値にしてくれる。 値は10進数で表記されるよ。
    • ん?         [65]?1と0の組み合わせじゃないじゃん?
    • 人間用とパソコン用。さっきの65は人間様が読みやすい用の 10進数で書いてる奴。 これをパソ用に2進数にしてやる。p value . to_s(2) # => 1000001
    • これが組み合わせ。 Aは  1000001  と組み合わせてある。 つまりなんやかんやで人間が インターフェイスを通して 【1000001】という バイナリ列をパソコンに伝える。 ・・・・・・・するとパソコンは画面に【A】という文字を表示してくれる。 人はこれをASCIIコードと呼ぶよね。
    • だけど、注意!さっきは、一文字分をバイナリ列で表現するといった。文字・・・【A】は文字だけど【1】は数字は?数値は?パソコンにとっては文字だろうが数値・数字だろうが 関係ない。 同じく、数値もバイナリ列で表現される。
    • 例えば? value = 1 value.to_s().encode("UTF-16BE").unpack( H*") ⇒  ["0031"] 数字の1・数値の1をバイナリ列にすると 10進数で[ 49 ]となるよ♪ さらに2進数にすると【 110001 】だよ。【1】という値は確かに数値としてみると、2進数も16進数も 【1】になるけど文字とバイナリ列の組み合わせを 行うからここでは別問題なんだよね。 言い換えれば【00000001】には既に他の文字が 組み合わされているってわけ♪
    • んでもってこの沢山の組み合わせを? 文字集合って呼んでいる。Unicodeってやつももちろん文字集合。
    • Unicodeとはなんぞや? Unicodeっていうのはアメリカの人たちが世界中の文字を【16ビット】つまり【2byte】で 文字を組み合わせようぜ!! って言い出したのがキッカケ。
    • でも16bitだと・・・・・。 16bitっていうのは2の16乗のこと。 つまり2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2=2^16 答え 65536通り 0 65535までの数値を表現できる。 これを1と0だけで表現すると65535 =【1111111111111111】だよ。
    • ゲームボーイ版の・・・。桃太郎伝説の最大所持金は 65536両。
    • 65536っていうことは 【1】 と【0】の組合わせが65536通り分。 文字と【1】 と【0】の組み合わせは 絶対に重複(ちょうふく・じゅうふく) してはいけない。 つまり65536通りの(しか)文字を表現できる。 【00000000 00000000】 ∼ 【11111111 11111111】の組み合わせにそれぞれ文字が割り当てられるってこと。
    • たとえば? 日本語の【あ】という文字。 これを文字集合の対応する組み合わせだと 確認してみる。value = "あ".encode("UTF-16BE").unpack("H*") ⇒  ["3042 ] パソコンが理解できるのは 【 00110000 01000010 】 の2進数表記だよ。
    • 日本語の【あ】とは。 Unicode文字集合上の16bitで全部表すっていう仕様の上では【3042】という2byteの組み合わせで 表現されちゃうよ!
    • でも、登録すべき文字が 予想より、多すぎた。 当初のUnicodeの仕様上の 16bitでの組み合わせじゃ 足りなくなっちゃった・・・・。(※いろんな国の人が文字を追加してくれって、言ってきたんだ ね。)
    • Unicodeの組み合わせの数は。Unicodeは、16bitの固定長で文字とバイナリ列を 組み合わせる(紐付ける)仕様。 つまり、 【00000000 00000000】 ∼ 【11111111 11111111】 までの組み合わせが 考えられる。これは16進数で【0x0000】∼【0xFFFF】となる。
    • でもね、実際は∼。 65536通りの組み合わせすべてに文字を割り当てていたわではなかったんだね。 実は、【D800】∼【DFFF】までは文字の割り当てが されていなかったらしいんだ。 【D800】∼【DFFF】の組み合わせって実は2048通りの【1】と【0】の組み合わせを 作れることがわかったんだね。
    • 偉い人たちは考えた。 どうやって、これまで組み合わせきた他の文字とバイト列をなくさないで文字とバイト列の組み合わせを 増やそうかと・・・・。2048通りの組み合わせがあっても、追加で増やしたい 文字はぶっちゃけ半端無く多い・・・。 2048文字程度の空きじゃ足りない。
    • 偉い人達は開き直った。 もうさ、もう世界中の文字を16bitで表現するの・・・・・・ 諦めようぜ? 追加分の文字はめんどくさいし桁増やそうぜ。
    • こうして、Unicodeの世界中の 文字16bitでよくね?計画は、破綻した。最終的に、これまで定義してきた根幹の16bit構想は 維持しつつ、追加分に関しては桁を増やして 5桁の、20bit(例えば 【0x20B9F】みたいな) で表そうということになった。でも、20bitっていも【2^20】(2の20乗)分すべての 組合わせをつかうわけじゃないよ。
    • ー符号化ー 【0xD800】∼【0xDFFF】までの もともとのUnicode内にベンチ入りしてた組み合わせを、まず半分んこする。 0xD800∼0xDBFF(1024通り) + 0xDC00∼0xDFFF(1024通り) 1024 1024=1048576通りの組み合わせを 保持できるよ。 あれ?これじゃさっきの5桁じゃなくね? 8桁になっちゃうよ? 【D800 DC00】みたいにさ? 言ってること違うじゃないか!!
    • サロゲート。 C#の無名関数みたいな奴はデリゲート。 スネちゃまはデリケート。 0xD800∼0xDBFF(1024通り) + 0xDC00∼0xDFFF(1024通り) 1024 1024=1048576通り人はこれをサロゲートペアと呼んだ!!(千葉繁風に) 0xD800∼0xDBFF(上位サロゲート) + 0xDC00∼0xDFFF(下位サロゲート)
    • ー8桁表記の文字を5桁表記へ。ー ーそれがUTF16。ーパソコンが実際に理解するバイナリ列をUnicodeとかで定義している文字集合と組み合わせるために効率的に表記する。 それが文字エンコーディング。 文字符号化。諸々。
    • ー符号化といっても?ー 当初Unicodeが定めていたいっちゃん最初の 65536通りの文字はそのままなんだよ。 てことは?例えば【あ】これは【0x3042】で表記されるよ。 でも、PC内でも同じように表記されるよ。 "あ".encode("UTF-16BE").unpack("H*") => ["3042"] そう、Rubyならね♪うん。だから【0x0000】∼【0xFFFF】までは 楽なんだよね!
    • 問題はね、追加分の文字だよね。 例えば【 】という文字があるよ♪ これはUnicodeの文字集合を見てみると【2000B】 というコードポイントと組み合わせされているよ♪ PC側ではどうなるの? $value = " ";$value = mb_convert_encoding($value,"UTF16","UTF8"); $binary = unpack( H* ,$value); print_r($binary); Array(  [1] => d840 dc0b ) そう!PHPならね♪
    • 32bit表記を20bit表記へ 8桁表記を5桁表記へ このサロゲートペアによる組み合わせを チョメチョメすることによって PC内部での表記【d840 dc0b】をUnicode上の表記【0x2000B】にすることができる。そう!エンコーディングで大変なのはここなんだ♪
    • PC上の符号化されたバイト列から 文字集合のコードポイントに復元しちゃお! 【d840 dc0b】の場合 d840 => 上位サロゲート dc0b => 下位サロゲート になるね。 さらに、上記の値から0xd840 - 0xd800(上位サロゲートの先頭) = 0x40 0xdc0b - 0xdc00(下位サロゲートの先頭) = 0xB 0x40 * 1024 + 0xB + 0x10000 = 【0x2000B】と、上記のような計算でUnicodeのサロゲート箇所の コードポイントを復元することができるよ。
    • では、UTF-16のまとめをするよ。
    • UTF-16の実態。その1 UTF-16とは? Unicodeの文字集合を表現するための エンコーディング方法の一つ。 当初、16bitだけで表現させようとしていたコードポイントは、継続して16bitで表現(※0x0000∼0xFFFFの組み合わせ) これをBMP【基盤他言語面 BMP】という。
    • UTF-16の実態。その2 後に、16bitで対応できなくなってしまった際に 追加した文字に対しては、コードポイント上では5桁・・・つまり20bitで表現するという仕様に変更した。 (※サロゲートペアによる組み合わせだね。) ただサロゲートペアの仕組みを実現するために ちょっとしたエンコーディングが必要になった。上位2バイト - 0xd800(上位サロゲートの先頭) = ①下位2バイト- 0xdc00(下位サロゲートの先頭) = ② ① 1024 + ② + 0x10000 = 符号位置 この計算式のことだよ。 ※RubyやPHPは特定の関数・メソッドでこの計算を やってくれてるんだね。
    • UTF-16の実態。その3つまりUTF-16で任意の文字を表現しようとした場合、 Unicode文字集合上では?=> 0x0000 0xFFFFまでは16bitな文字。 0xFFFFの値を超える コードポイントに関しては 20bitな文字。 PCの内部では?=>0x0000 0xFFFFまでは16bitな文字(2byte文字)0xFFFFの値を超えるコードポイントに関しては 32bitな文字(4byte文字) として認識される。
    • UTF-16の実態。その4もっと掻い摘んでいうと。=>エンコーディング (符号化)とはPC内部で文字を表記しているバイナリ列を人間が定義した文字集合上のコードポイントに復号させるための方法・定義など。たぶん。
    • では、次のページからUTF­8についてまとめてみるよ。
    • UTF-8とUTF-16の違いとは?その1 ここまで、まとめたUnicodeの仕様を踏まえつつ次はUTF-8のエンコーディングについてまとめてみる。例えばUTF-16のエンコーディングにおいて【あ】は どのようなバイト列だったろうか? 次の例を見てみてね♪
    • UTF-8とUTF-16の違いとは?その2<?php $value = あ ; $value = mb_convert_encoding($value, UTF16 , UTF8 ); print_r(unpack( H* ,$value)); //以下出力結果だよ。 [1]=>[3042] という値を取得することになる。
    • UTF-8とUTF-16の違いとは?その3では次に、UTF-8における【あ】のバイト列はどのような値が取得できるのだろうか?<?php $value = あ ; $value = mb_convert_encoding($value, UTF8 , UTF8 ); print_r(unpack( H* ,$value)); //出力結果 ["e38182"] ・・・・・・・・うーん? UTF-16の時とは似ても似つかない バイト列が返って来たね・・・。これはいったい?・・。
    • UTF-8とUTF-16の違いとは?その4実はUTF-8って、UTF-16とは違ってPC内部側では、大部分の日本語は3byteで表記される。[ e38182 ]=>よく見ると16進数記法で6桁ある・・・・・。つまり、3byteで符号化(エンコーディング)されてるね!逆にUTF-16の時は[ 3042 ]=>だった。これはUnicodeの文字集合そのままの値だったね。うん!UTF-16は、BMP面の文字に対しては16bitで文字を割り当てる。さらに、BMP面外(サロゲートペアによる組み合わせ)はPC内部側では32bit(4byte)が割り当てられていたね。
    • UTF-16は【2byte】あるいは【4byte】じゃあ UTF-8は?いったい何byteでエンコードされているのか?UTF-16のエンコーディング方式は比較的ラクだった。けど、UTF-8はちょっと複雑だよ。実は、UTF-8ってPC内部での表記が【1byte】【3byte】【4byte】と複数の割り当て方が存在しているんだよね・・・・。まず、【1byte】で表記された場合これは256通りの文字割り当てが可能ですが、ここにはASCIIコードとの互換保持のためASCIIコードがまるごと定義されているのです。だからA∼Zのアルファベットや0∼9までの数字なんかはすべてASCIIと同じコードポイントが定義されているんだ。
    • UTF-8でエンコーディングした時の復号方法は?じゃあ、UTF-8でのバイト列をどうやって文字集合上のコードポイントに変換・復号するのだろうか。例えば#Rubyだよ。#まず、単純に数値の場合。testValue ="1";p testValue . encode("UTF-8") . unpack( H*")[31] => [31]お!これはASCIIコードがそのまま出てきたね。これは1byteだね。
    • UTF-8で日本語の扱いはどうなってるのか?testValue = あtestValue . encode("UTF-8").unpack("H*")⇒  ["e38182"]ん?16進数の6桁ということは3byteのバイト列で構成されてるね。でも実際の文字集合上の【あ】のコードポイントは【3042】だね。つまりこれからスクリプトが自動でUTF-8の符号化方法に法ってUnicodeで定義されているコードポイントに直してくれるわけだ。
    • UTF-8で3byteで符号化されている文字を Unicodeコードポイントに復元してみる。①まず、[ e38182 ]という値を1byteずつ2進数に変換する。E3 => 1110001181 => 1000000182 => 10000010②上記で算出した2進数をRFCの定義に則って加工する。11100011 => 0011(下位4bitを抜き取る)10000001 => 000001(下位6bitを抜き取る)10000010 => 000010(下位6bitを抜き取る)③上記で抜粋したビット箇所をくっつける。【00110000 01000010】すると16bitのバイナリ列ができあがるのでこれを16進数に変換してみると?【3042】というUnicode上の「あ」という文字のコードポイントを算出できる。※UTF-8の符号化されたバイト列を、Unicodeのコードポイントに復元する方法は、それに明るサイトを参照。http://lab.moyo.biz/translations/rfc/rfc2044-ja.xsp上記サイトの、2. UTF-8 定義の項目を参照のこと。
    • 今の符号化を言語がすべてやってくれるのか・・。 RubyとかPHPとか・・・あいつら意外にやるじゃん?正直、RFCの計算方法はなんであんな方法なかのかはわかりません。とりあえず、あのような方法で復元できるということ。そして・・・・。RubyやPHPやPerlならunpackやpackC#やJavaならEncoding系クラス及びGetBytes系メソッドが今のをやってくれる。
    • 次のページでUTF-8についてまとめるよ∼。
    • UTF-8の実態。その1 UTF-8とは? Unicodeの文字集合を表現するための エンコーディング方法の一つ。 でも、UTF-16の初期みたく固定長じゃないよ。 可変長byteで符号化されてる。 UTF-16とは異なり、ASCIIコードと互換性もつよ。ASCIIと同じ7bit分の全く同じコードポイントをもってるよ。
    • UTF-8の実態。その2 符号化した時、可変長。UTF-16もBMPとサロゲートペア箇所はそれぞれ Byte数の異なる可変長だけどね。 UTF-16とは異なり、UTF-8は 【1byte】【2byte】【3byte】 果ては、【4byte】とかもあるよ。
    • UTF-8の実態。その3RFCでUTF-8の符号化・復号化の算出方法が定義されてる。 符号化 1byteの時はそのままコードポイントになる。2byte以降は、復号のためのちょっとした計算をしなくちゃ ならないよ。 でも、そういうのは組み込み関数がやってくれる。 Ruby => encodeメソッドとか PHP => mb_covert_encoding関数とかね。
    • まとめ。その1 1.Unicode(文字集合)とは・・・。 【文字】と【文字を紐付けるための符号位置】を組み合わせたものをたくさん定義した表のこと。 2.Unicodeと文字エンコーディングとは・・・。 文字集合を元に、符号位置を再現するために バイナリ列を定義する仕様。 「UTF-8」も「UTF-16」も「UTF-32」も同じUnicodeという文字集合を別々のバイナリ列で 表現するための方法。
    • まとめ。その2 3. バイナリ列の復号・・・。 各エンコーディングによって文字集合上のコードポイントへバイナリ列を復号する 復号方法がそれぞれ異なる。 おわり。