Unicode拡張領域の取り扱い

Java / Scala

Unicodeエスケープは16ビットまでの文字しか書けないので、拡張領域の文字をUnicodeエスケープで書くにはサロゲートペアで2つの16ビットに分割する必要がある。

Scalaでの例

println("地球🌍"); // 3文字目は地球の絵文字
// => 地球🌍

val str = "\u5730\u7403\uD83C\uDF0D";
println(str);
// => 地球🌍

val len = str.length;
println(len);
// => 4

println(str.codePointCount(0, len));
// => 3

val str2 = "🌍";
println(str2.codePointAt(0));
// => 127757

val str3 = new String(Array(127757), 0, 1);
println(str3);
// => 🌍

PHP

PHPではUnicodeをネイティブには対応しておらず、単なるバイト配列である。 UTF-8で文字列を処理するのであれば、UTF-8のバイナリを書けば Unicodeの拡張領域の文字もいちおうは書くことができる。

$str = "地球🌍"; // 3文字目は地球の絵文字
echo "$str\n";
// => 地球🌍

$str = "\xE5\x9C\xB0\xE7\x90\x83\xF0\x9F\x8C\x8D";
echo "$str\n";
// => 地球🌍

// strlen は文字数ではなくバイト配列の長さ
echo strlen($str) . "\n";
// => 10

Python

Python3では文字列に直接拡張領域の文字を書くこともできるし、 \U00hhhhhh の形式のエスケープシーケンスでも拡張領域の文字を使える。

拡張領域の文字を気にすることなく各種関数をそのまま使える。

Python3での例

str = "地球🌍" # 3文字目は地球の絵文字
print(str)
# => 地球🌍

str = "\u5730\u7403\U0001F30D"
print(str)
# => 地球🌍

print(len(str))
# => 3

str = "\U0001F30D"
print(ord(str))
# => 127757

print(chr(127757))
# => 🌍

str = "\u5730\u7403\U0001F30E\U0001F30D"
print(str.find("\U0001F30D"))
# => 3

Python2ではUnicodeのエスケープを使えるのはUnicode文字列リテラル(u"...")の中のみである。 chr関数は8ビットを超えるUnicode文字を扱えず、代わりに unichr 関数を使う必要がある。

Python2での例

str = "地球🌍" # 3文字目は地球の絵文字
print(str)
# => 地球🌍

str = u"\u5730\u7403\U0001F30D"
print(str)
# => 地球🌍

print(len(str))
# => 3

str = u"\U0001F30D"
print(ord(str))
# => 127757

print(unichr(127757))
# => 🌍

str = u"\u5730\u7403\U0001F30E\U0001F30D"
print(str.find(u"\U0001F30D"))
# => 3

Ruby

文字列には直接拡張領域の文字を書くこともできるし、 \u{hhhhh} の形式のエスケープシーケンスでも拡張領域の文字を使える。

p "地球🌍" # 3文字目は地球の絵文字
# => "地球🌍"
p "\u{5730 7403 1F30D}"
# => "地球🌍"

p "\u{5730 7403 1F30D}".length
# => 3

p "🌍".ord;
# => 127757

p 127757.chr("UTF-8")
# => "🌍"

p "\u{5730 7403 1F30E 1F30D}".index("\u{1F30D}")
# => 3

Perl

use utf8; と宣言しておけば、文字列には直接拡張領域の文字を書くこともできるし、 \x{hhhhh} の形式のエスケープシーケンスでも拡張領域の文字を使える。

use utf8;
use Encode qw/encode_utf8/;

print encode_utf8("地球🌍\n"); # 3文字目は地球の絵文字
# => 地球🌍
print encode_utf8("\x{5730}\x{7403}\x{1F30D}\n");
# => 地球🌍

print length("\x{5730}\x{7403}\x{1F30D}");
# => 3

print ord("🌍");
# => 127757

print encode_utf8(chr(127757));
# => 🌍

JavaScript

Javaと同じく、Unicodeエスケープは16ビットまでの文字しか書けないので、拡張領域の文字をUnicodeエスケープで書くにはサロゲートペアで2つの16ビットに分割する必要がある。

console.log("地球🌍"); // 3文字目は地球の絵文字
// => 地球🌍

var str = "\u5730\u7403\uD83C\uDF0D";
console.log(str);
// => 地球🌍

var len = str.length;
console.log(len);
// => 4

上記実行例は nodejs v0.10.15 で確認。

サロゲートペアに対応した文字数取得などはJavaScriptには存在せず、以下のようなライブラリが必要。

javascript - でBMP以外のUnicode文字をきちんと扱う
http://blog.livedoor.jp/dankogai/archives/51861512.html

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。