社内SEになりました

社内SEは本当に楽なのか?ユーザー系IT企業とSierとの違いは?これからIT企業への就職や転職を考えている人むけに、ユーザー系IT企業から社内SEに40代で転職した筆者がITエンジニアの仕事内容やプロジェクト管理のノウハウ等をご紹介。

文字コード第五回:サロゲートペア

文字コードって、とっても難しいです。

そんな文字コードの中で、サロゲートペアについて、可能な限りわかりやすく解説します。

1.サロゲートペアとは

UTF-16 は基本は 2 バイトで 1 文字ですが、2 バイトで表せる文字は 256 × 256 = 65,536 と世界中の文字を収録するには不足するため、苦肉の策として 4 バイトで 1 文字を表すこととしました。

ただ全部の文字を 4 バイトにしてしまうと、それまで UTF-16 を利用していたシステムに大きな影響が出てしまうため、基本は 2 バイト 1 文字のままで、65,536 で収まらない文字だけ 4 バイト 1 文字としました。

この 4 バイト 1 文字で表される文字をサロゲートペアと呼びます。

古いプログラムでは、UTF-16 は 2 バイト固定の前提で処理をしているので、文字列操作でエラーが起きる可能性があり、注意が必要です。

ちなみに全部の文字を 4 バイト 1 文字にした文字コードは、UTF-32 です。

2.サロゲートペアの見分け方

サロゲートペアは 4 バイト 1 文字ですが、この 4 バイトは「 2 バイト」+「 2 バイト」で構成されています。

最初の「 2 バイト」を上位サロゲート、次の「 2 バイト」を下位サロゲートと呼びます。

上位サロゲートのコード範囲は D800 〜 DBFF で、下位サロゲートのコード範囲は DC00 〜 DFFF です。

f:id:SystemEngineers:20210705202031p:plain

このサロゲートペアで表せる文字数は 1,024 × 1,024 = 1,048,576 文字となり、現状の Unicode の最新バージョン 13.0.0 に収録されている文字数 143,859 文字を軽く上回ります。

3.サロゲートペアの作り方

Unicodeの U+0000 〜 U+FFFF までは、2 バイトで表すことができるので、U+10000 からがサロゲートペアとなります。

Unicodeは、理論上は最大 4 バイトですが、国際ルールで最大値が U+10FFFF(21ビット) と決まっています。

そのためサロゲートペアになる最大の文字数は、10FFFF − 10000 = FFFFF = 1,048,576 文字となり、ちょうど上位サロゲートと下位サロゲートで表せる文字数と一致します。(一致するように上位サロゲートと下位サロゲートを決めたというのが正確な言い方かもしれません)

そこでサロゲートペアが U+10000 から U+10FFFF の間にある前提で、Unicode の符号位置から 10000 を引き、その結果の 20 ビットの前半 10 ビットを以下のように上位サロゲートに、後半 10 ビットを下位サロゲートマッピングすることで、サロゲートペアの文字コードが作られます。

f:id:SystemEngineers:20210706074440p:plain

例えば「𦥑」の Unicode は U+26951 です。ここから 10000 を引くと 16951 となり、これをビットで表すと 0001 0110 1001 0101 0001 となります。

この 20 ビットの前半 10 ビットを上位サロゲートにあてはめ 1101 1000 0101 1010( D8 5A )、後半10ビットを下位サロゲートにあてはめ 1101 1101 0101 0001( DD 51 )となります。

f:id:SystemEngineers:20210709144900p:plain

f:id:SystemEngineers:20210709144911p:plain

4.Unicodeの中のサロゲートペア

Unicodeは、群、面、区、点で構成されます。

このうち群 00、面 00 が当初の Unicode( 2 バイト文字)で BMP と呼ばれています。

2 バイトで収まらなかった文字(漢字)は、面 02 に収録され、それらが UTF-16 ではサロゲートペアとなります。

f:id:SystemEngineers:20210709162507p:plain

5.まとめ

UTF-16は 2 バイト文字なので、最大 65,536 文字を収録できますが、そのうち D800 〜 DFFF のエリア( 2,048 文字分)をサロゲートペア用に割り当てているため、 65,536 − 2,048 = 63,488 文字が2バイトで表すことができる最大の文字数となります。これにサロゲートペアの 1,048,576 文字を加えることで、UTF-16 で表せる文字数の最大は 1,112,064 文字となります。

f:id:SystemEngineers:20210709163644p:plain

 【振り返り】

第五回は、サロゲートペアでした。第六回は、IVS です。

第一回:概要
第二回:符号化文字集合
第三回:文字符号化方式(前編)
第四回:文字符号化方式(後編)
第五回:サロゲートペア
第六回:IVS
第七回:文字コードの歴史
第八回:文字化け

今週のお題「住みたい場所」

はてなブログ今週のお題「住みたい場所」

沖縄の石垣島

昨年と今年はコロナ禍で自粛していますが、20年前に石垣島に行って以来、ほぼ毎年、帰省しています。

石垣島の良いところはいろいろありますが、私は寒さに弱いので何よりも気候。暖かいとそれだけで、なんとかなりそうな気がします。なんくるないさぁです。

石垣島は仕事が少なそうなので、コロナ禍前はリタイア前の移住は考えてませんでしたが、テレワークが常態化した今となっては、移住をしない理由がなくなってしまいました。

私の本気度が試されるときがやってきたわけですが、住みたい場所と住む場所は違うのだという現実を突きつけられた感じです。

f:id:SystemEngineers:20210704200542j:plain

そこかぁ!

ギフトセンター最終日の応援。

わざわざ店舗なんかに来ないで、ネットで注文した方が楽なのにと思いながらも、当然口には出さずに承り。

ふとお客さんの一人に、まだネットだと優待きかないままですよね?と尋ねられ、はっと大切なことに気づきました。

自社カードを提示するとギフトが10〜15%引きになるのですが、ECサイトで優待がきくのは自社のクレジットカード払いのときだけ。

店舗だと現金ポイントカードや自社のアプリを見せるだけでも優待がききます。

灯台下暗し。

まさかお客さまがネットを使わず来店する理由の一つが、システムだったとは・・・。

店舗と同じサービスレベルを実現しなければと、反省です。

RFP発出!

昨日から、中途入社して3年目がスタートしました。

そして今日、8ヶ月ほどかけて実施した要求定義が終わり、ベンダー5社にRFPを発出。

この2年の間、億超えのプロジェクトを他に2つ任されていましたが、一つは要求定義の途中で白紙に、もう一つは要件定義中の経営判断で中止に・・・。

どうか3度目の正直で、本番リリースまで無事に続けられますように。

今週のお題「一気読みした漫画」

はてなブログ今週のお題「一気読みした漫画」

何年くらい前か忘れましたが、DEATH NOTE を一気読みしました。

最初は全く興味がなかったのですが、映画にもなって、たびたび話題になっていたので、漫画喫茶で読んでみたところ面白くて、一気に全巻読破してしまいました。

DEATH NOTE を読み終わって思い出したのは、子供のころ読んでいた推理小説のドキドキ感。子供のころは「楽しいか」「楽しくないか」の 2 択しかなくて、それが自分の糧になるかなんて全く気にしてませんでした。

でも大人になってからは、推理小説は「得るものがない」ような気がして、なんとなく読まなくなっていました。

仕事を頑張っているうちに、いつの間にか、そんな楽しみ方もあるんだということを忘れていたみたいです。

f:id:SystemEngineers:20210627175504j:plain

文字コード第四回:文字符号化方式(後編)

文字コードって、とっても難しいです。

そんな文字コードの中で、文字符号化方式について、可能な限りわかりやすく解説します。

1.UTF-16UTF-32

ISO-2022-JPEUC-JP 、Shift-JIS は、複数の文字集合を利用するための文字符号化方式です。

それに対して、UTF-16UTF-32UTF-8 といった文字符号化方式は、使用している文字集合Unicode のみです。

それなら Unicode を直接利用すれば良いのでは?と普通の人は思います。

そして実際に最初は Unicode を直接利用していました。JavaC# などは今は UTF-16 を利用していると言われていますが、当初は UTF-16 というより Unicode を利用していました。

当時の Unicode は、2 バイトの固定長でした。

2 バイトの固定長だと収録できる文字数は、256 × 256 = 65,536 で、世界中の文字を収録するには全然足りませんでした。

そこで 4 バイトに拡張した UTF-32 が登場し、それまでの UnicodeUTF-16 と呼ばれるようになりました。そして新しい Unicode は 8 〜 21 ビットの可変長となり、直接利用されることがなくなりました。

そのため UTF-16 を利用している大部分のソフトウェアは、当初は Unicode を利用していたのです。

このように Unicode、UTF16、UTF-32 は固定長か可変長の違いはありますが、基本的には同じコードになります。ただし UTF-16 は 65,536 を超える文字を表現するために、サロゲートペアと呼ばれる 2 文字分のコードで 1 文字を表す手法を使っていますので、UTF-16サロゲートペアは、文字コードが異なります。

f:id:SystemEngineers:20210626075857p:plain

 2.リトルエンディアンとビッグエンディアン

UTF-16UTF-32 で少し厄介なのが、リトルエンディアン( LE )とビッグエンディアン( BE )です。

2 バイト文字の 1 桁目から格納する方式をビッグエンディアン、2 桁目から格納する方式をリトルエンディアンと呼びます。

f:id:SystemEngineers:20210626081335p:plain

これはデータをアドレス空間に格納する際、CPU によってデータの先頭から格納していく方式( BE )とデータの最後尾から格納していく方式( LE )が存在することに影響を受けています。

インテル系の CPU は LE を採用しています。プロトコルだと TCP/IP は BE 、USB は LE を採用していたり、JVMはBEを採用していたり、バラバラです。

このエンディアンが一致していると処理効率が良いのですが、逆になると少し処理効率が落ちます。

f:id:SystemEngineers:20210627115200p:plain

このエンディアンの考え方は、EUC-JP や ISO-2022-JP、Shift-JIS にはありません。

これらは「半角」文字は 1 バイトで、「全角」文字は 2 バイトですが、UTF-16(当時のUnicode)は全て 2 バイトです。

当時はコンピューターの処理能力が今ほど大きくなく、この文字のデータサイズの差を少しでも埋めるために、CPU やソフトウェアの処理効率が少しでも上がるようにエディアンの考え方を取り入れました。

さらにこのエンディアンには、BOM(Byte Order Mark)と呼ばれるコードがあります。

BOM を文字列の先頭につけることで、その文字列が BE なのか LE なのかを区別することができるようになります。

BE の BOM は FE FF で、LE の BOM は FF FE となります。

BOMをつけない場合には、文字符号化方式自体でBEかLEを宣言することになります。

つまり同じ UTF-16 でも、UTF-16 BE、UTF-16 LE、UTF-16 の3種類があり、さらにデータの並び順の違いも入れると、UTF-16 BE、UTF-16 LE、UTF-16( BE の BOM 付)、UTF-16( LE の BOM 付)、UTF-16( BOM なし)の5種類になります。

f:id:SystemEngineers:20210626185253p:plain

UTF-16( BOM なし)は、BE として扱われることが多いようです。

3.UTF-8

UTF-16 にはサロゲートペアの問題があり、UTF-32 は先頭 2 バイトの大部分が 0000 でメモリー利用効率が悪く、どっちもいまいちです。

そこで登場したのが UTF-8 です。

UTF-8 は可変長のため、固定長の文字コードよりも扱いにくいですが、コンピューターの処理性能が上がったことと、ASCⅡ と互換があることから、今や大部分のソフトウェアでは UTF-8 が使われるようになってきました。

UTF-8 は、UTF-16UTF-32 と違い、Unicode とは似ても似つかないコードになります。

f:id:SystemEngineers:20210626204140p:plain

UTF-8 の符号化方式は、以下のルールに従います。

f:id:SystemEngineers:20210626213006p:plain

このルールに従って UnicodeUTF-8 に変換すると以下のようになります。

f:id:SystemEngineers:20210626213124p:plain

U+0031 は、UTF-16 は「00 31」、UTF-32 は「00 00 00 31」です。それに対してUTF-8 は「31」で、ASCⅡ と全く同じなので重宝されているようです。

ただ漢字は 3 バイトや 4 バイトとなり、EUC-JP や ISO-2022-JP、Shift-JIS といった符号化方式よりもサイズが増えるため、一長一短なところはあります。

f:id:SystemEngineers:20210627102850p:plain

この UTF-8 にも BOM があります。

UTF-8 の BOM は「EF BB BF」です。本当は 2 バイトコードではない UTF-8 には BOM は必要ないのですが、UTF-8 であることを示すために付加されることがあります。

例えば WindowsPC で CSV ファイルをダブルクリックすると、Excel でファイルが開かれますが、このとき ExcelCSV文字コードを CP932 として扱います。もし CSV文字コードUTF-8 で作成していると、CP932 として扱われるので文字化けします。

このとき、CSV を BOM 付きの UTF-8 で作成すると、Excel は正しく UTF-8 として扱ってくれるので文字化けしません。

ただし UTF-8 の BOM に対応していないソフトウェアもあるので、その場合には「EF BB BF」も文字として扱ってしまい、文字化けの原因となるので注意が必要です。

4.まとめ

符号化文字集合文字符号化方式の説明は以上となります。

これらを図にすると以下のようになります。ちょっとごちゃごちゃして見にくいですが・・・。

f:id:SystemEngineers:20210626214735p:plain

以下は、文字コードのサンプルです。

f:id:SystemEngineers:20210705213210p:plain

どの文字コードも ASCⅡ との互換を大切にしていることがわかります。

 【振り返り】

第四回は、文字符号化方式(後編)でした。第五回は、サロゲートペアです。

第一回:概要
第二回:符号化文字集合
第三回:文字符号化方式(前編)
第四回:文字符号化方式(後編)
第五回:サロゲートペア
第六回:IVS
第七回:文字コードの歴史
第八回:文字化け

職域接種

うちの会社でも職域接種がはじまりました。

全社員分のワクチンが確保できていないため、店舗勤務の人が優先され、本社勤務の私は申し込みしても日付の指定はできません。

そもそも注射が死ぬほど嫌いなので、絶対に申し込みはしませんが・・・

これから「まだワクチン打ってないの?」という無言のプレッシャーをかけられないか、心配です。