書いた人: 成瀬
Ruby 1.8 になって標準添付ライブラリが増えました。そんなライブラリをどんどん紹介していこうという連載です。
今回は Kconv, NKF, Iconv といった、文字コード変換のためのライブラリを紹介します。
文章を読もうとしたら文字化けしてしまっていて困った、という経験は誰しもあるでしょう。しょうがないので調べると、文字コードを変換すれば読めるようになる、などとの説明を見つけることが出来るでしょう。多くの方の「文字コードとの出会い」は、おそらくこのあたりなのではないでしょうか。さて、そんな文字コードですが、そもそもいったい何者なのでしょうか。
文章をコンピュータで扱おう思うと、文字をコンピュータで扱わなければなりません。しかし、ご存知のとおり、基本的にコンピュータは 0 と 1 しか扱えないため、文字をコンピュータが扱える形に変換する (符号化する) 仕組みが必要となります。この仕組みが文字符号化であり、符号化の仕方の一つ一つが文字コードです。
コンピュータの扱う情報量の最小単位は 0 か 1 によって表される情報量であり、これを bit と呼びます。通常は 8bit (1octet) を一組にして 1byte とし、これを基本にしてコンピュータは情報をやりとりします。文字も同様に byte を一単位としてやりとりすることになります。つまり、文字コード1とは、文字を byte の列に変換する体系のことと言えるのです。
文字コードは一つではありません。例えば日本語を表すのに用いられる文字コードには、主に以下のようなものがあります。
異なる文字コードで表された文章は、一般に異なるバイト列に変換されます。そのため、例えば Shift_JIS で表された文書を、 EUC-JP として表示しようとすると、正しくその文書を見ることが出来ません。これが文字化けです。
文字化けの解決方法は二つあります。
一つはその文書を正しい文字コードで表示することです。多くのプログラムはいくつかの文字コードに対応しているので、正しい文字コードで表示しなおせば、文書を見ることが出来ます。この例の場合では、 Shift_JIS として文書を開きなおせば文字化けせずに読めます。
もう一つはその文書を都合のいい文字コードに変換する事です。文字コード変換プログラムによって、自分の扱いやすい文字コードに変換してしまえば、後は気楽にその文書を扱う事が出来ます。この例の場合では、 Shift_JIS から EUC-JP に文書の文字コードを変換してしまえばいいのです。
さて、では実際に Ruby で文字コードを変換してみましょう。Ruby では主に以下のような文字コード変換ライブラリが用いられており、このうち最初の三つの文字コード変換ライブラリは ruby に標準で添付されています。
なお、紛らわしい名称のライブラリとして、 jcode.rb が存在しますが、これは Perl の jcode.pl とは役割が異なり、Ruby に文字志向の処理を行わせるためのモジュールです。
Ruby 1.8.2以降においては、日本語の文字コード変換は Kconv を使えば、たいていの場合は事足りるでしょう。それ以前の Kconv でも、 Unicode 系の変換は出来ませんが、Shift_JIS, EUC-JP, ISO-2022-JP の相互変換が可能です。
なお、 Kconv は自動的に、 MIME をデコードしたり、半角カタカナを全角カタカナに変換したりしてしまいますが、このような動作を好まない場合は、後述のとおり、 NKF モジュールを直接用いる必要があります。
最も容易なのは Kconv#to* を用いる事でしょう。これでは変換元の文字列の文字コードを推測し、文字コードを変換します。以下に例を示します。
先述の Kconv#to* では変換元の文字コードを推測しているため、推測が外れていた場合は変換結果が文字化けしてしまいます。このような危険性を避けるため、変換元の文字コードが分かっている場合は、なるべく文字コードを明示的に指定するようにしましょう。
Kconv では文字コードは定数で指定します。
定数 | 値 | 文字コード |
JIS | 1 | ISO-2022-JP |
EUC | 2 | EUC-JP |
SJIS | 3 | Shift_JIS |
BINARY | 4 | バイナリ |
ASCII | 5 | ASCII |
UTF8 | 6 | UTF-8 |
UTF16 | 8 | UTF-16 |
これらの定数を用いて、例えば以下のように変換を行います。
Kconv.guess によって与えられた文字列の文字コードを推測することができます。
なお、Kconv.guess による文字コードの推測は、 UTF-16 については BOM 付きにのみ対応しています。
ruby 1.8.2 の Kconv には以下のようなバグが存在します。
NKF モジュール由来のバグで、文字コードの自動判定精度が下がっています。変換元の文字コードが分かっている場合は、to* 系のメソッドを用いず、 String#kconv や Kconv.kconv 、 NKF.nkf を用いて、変換元の文字コードを明示的に指定するようにしましょう。
なお、この問題は ruby 1.9 及び ruby 1.8 系の最新版では既に修正されており、 ruby 1.8.3 では修正された版が添付されます。
ruby 1.8.2 でこの問題を回避したい場合は以下のような方法が挙げられます。
i386-freebsd4 ならば、 2.0.5-i386-freebsd4 を用いることもできます。一応さくらインターネットのレンタルサーバでの動作を確認はしています、保障は出来ませんが。
ruby 1.8.2 に添付されている kconv.rb では String#kconv 及び Kconv.kconv において、 Unicode系の文字コードの指定ができないバグが存在します。
なお、この問題は ruby 1.9 及び ruby 1.8 系の最新版では既に修正されており、 ruby 1.8.3 では修正された版が添付されます。
ruby 1.8.2 でこの問題を回避したい場合は以下のような方法が挙げられます。
ものすごく古い漢字コード変換プログラムである nkf を Ruby から用いるためのライブラリです。1.8.2 から nkf 2.0 ベースになったため、 Unicode 系の変換に対応しました。上記の Kconv は、内部では NKF を用いて変換を行っています。
NKF は変換を converted = NKF.nkf( option_string, string ) といった文法で行います。オプションを文字列として与える方法は複雑で覚えづらいものではありますが、その一方で Kconv を使う場合に比べてはるかに複雑な処理を行うことが可能となります。なお、オプションは NKF モジュールのベースとなっている nkf のオプションをほぼ全て使うことが出来ます。
出力する文字コードを指定します。
文字コード | オプション | ロングオプション |
EUC-JP | -e | –euc |
Shift_JIS | -s | –sjis |
ISO-2022-JP | -j | –jis |
UTF-8N | -w | –utf8 |
UTF-8 BOM | -w8 | |
UTF-8N | -w80 | |
UTF-16BE N | -w16 | –utf16 |
UTF-16BE BOM | -w16B | |
UTF-16BE N | -w16B0 | |
UTF-16LE BOM | -w16L | |
UTF-16LE N | -w16L0 |
入力する文字コードを指定します。指定しなくても自動判定が効きますが、誤判定のリスクを避ける意味でも、入力する文字コードが分かっている場合は明示的に指定するべきです。
文字コード | オプション | ロングオプション |
EUC-JP | -E | –euc-input |
Shift_JIS | -S | –sjis-input |
ISO-2022-JP | -J | –jis-input |
UTF-8N | -W | –utf8-input |
UTF-8 BOM | -W8 | |
UTF-8N | -W80 | |
UTF-16BE N | -W16 | –utf16-input |
UTF-16BE BOM | -W16B | |
UTF-16BE N | -W16B0 | |
UTF-16LE BOM | -W16L | |
UTF-16LE N | -W16L0 |
改行コードを変換します。
改行 | オプション | 使われるシステム |
LF | -Lu, -d | Unix系 |
CRLF | -Lw, -c | Windows |
CR | -Lm | Macintosh |
MIME decode/encode のためのオプションです。 nkf はデフォルトで MIME encoded-word のデコードを試みるため、この動作を望まない場合は -m0 を指定してください。
-X を指定すると、 nkf は半角カタカナを自動的に全角カタカナに変換します。 -X はデフォルトで指定されているため、この動作を望まない場合は -x を指定してください。
Windows 互換の文字コード変換、つまり CP932 や eucJP-ms 互換の変換を行います。具体的には、「??????|」のような文字を Unicode へと変換した時に化ける問題や、 Windows の機種依存文字が変換できない問題は、このオプションを指定する事によって回避することができます。
ひらがなやカタカナを相互に変換します。
オプション | ロングオプション | 機能 |
-h1 | –hiragana | カタカナをひらがなに変換 |
-h2 | –katakana | ひらがなをカタカナに変換 |
-h3 | –katakana-hiragana | カタカナとひらがなを交換 |
禁則を考慮した折り返しを行います。禁則は通常半角 60 文字で行われますが、明示的に -f40 と指定すると半角 40 文字で、 -f80 と指定すると半角 80 文字で折り返します。
通常、禁則は半角 10 文字までの範囲で禁則文字をぶら下げ、それ以上は強制的に改行しますが、明示的に -f40-5 と指定すると強制改行の余地 (fold-margin) を半角 5 文字に指定できます。禁則処理を行わない場合は -f40-0 などと指定します。
-f では改行が全て半角空白に置き換えられてしまいますが、 -F では改行が保存されます。
ruby 1.8.2 の NKF には以下のようなバグが存在します。
NKF モジュール由来のバグで、文字コードの自動判定精度が下がっています。変換元の文字コードが分かっている場合は、 NKF.nkf を用いて、変換元の文字コードを明示的に指定するようにしましょう。
なお、この問題は ruby 1.9 及び ruby 1.8 系の最新版では既に修正されており、ruby 1.8.3 では修正された版が添付されます。
ruby 1.8.2 でこの問題を回避したい場合は以下のような方法が挙げられます。
i386-freebsd4 ならば、 2.0.5-i386-freebsd4 を用いることもできます。一応さくらインターネットのレンタルサーバでの動作を確認はしています、保障は出来ませんが。
UNIX 系で主に使われる iconv を Ruby から利用するためのライブラリです。そのシステムに存在する iconv を利用するため、実際にどのような文字コードを利用できるかはプラットフォームに依存します。
Iconv クラスには様々なメソッドがありますが、通常は Iconv.conv を用いればいいでしょう。
Iconv.conv は
のように用います。
それぞれの引数の意味は以下の通りです。
なお、変換先・変換元の文字コードを指定する文字列も、プラットフォームに依存します。しかし、この問題は charset_alias.rb という仕組みによって解決が図られており、日本語では ‘Shift_JIS’, ‘cp932’, ‘EUC-JP’, ‘UTF-8’ は、実装されていれば、それぞれの文字列で指定できるようになっています。
Windows 機種依存文字等の日本語関係の文字コード変換を Iconv モジュールで行うには、対策を施してある iconv ライブラリを用いる必要があります。具体的には以下のライブラリを使う事になるでしょう。
その他の iconv 、例えば NetBSD Iconv (Citrus Iconv) では、いくつか2の機種依存文字が変換できないため、 pkgsrc 等から libiconv を別途インストールして用いる必要があります。
また、 Windows の機種依存文字を含んだ Shift_JIS は cp932 を、 EUC-JP は eucJP-ms を指定する必要があります。
FreeBSD 等のように標準で、 iconv 等が /usr/local 下にインストールされる OS の場合、ruby を自分で make すると Iconv 等がインストールされない場合があります。このような場合には、 configure する際に iconv 等の位置を指定しましょう。
Uconv は Unicode 系と CP932 および EUC-JP との相互変換を行います。また、その他 UTF のバイトオーダーに関する処理等も行う事が出来ます。なお、レンタルサーバーを使っている等の事情で C 言語版の Uconv を用いる事が出来ない場合は、 PureRuby 版である rbuconv を用いるとよいでしょう。
ここにおいては、基本的に UTF-16 および UTF-32 は常にリトルエンディアンです。ビッグエンディアンでの文字列が欲しい場合は後述の u16swap または u4swap によって、エンディアンを変更する必要があります。
変換元?変換先 | EUC-JP | CP932 | UTF-8 | UTF-16LE | UTF-32LE |
EUC-JP | ? | - | euctou8 | euctou16 | - |
CP932 | - | ? | sjistou8 | sjistou16 | - |
UTF-8 | u8toeuc | u8tosjis | ? | u8tou16 | u8tou4 |
UTF-16LE | u16toeuc | u16tosjis | u16tou8 | ? | u16tou4 |
UTF-32LE | - | - | u4tou8 | u4tou16 | ? |
Unicode でのバイトオーダー変更、つまりビッグエンディアンとリトルエンディアンを相互変換します。
エンコーディング | メソッド名 |
UTF-16 | u16swap |
UTF-32 | u4swap |
様々な界隈に首を突っ込む多趣味な子。最近は文字コード関連に興味を持っているが、なんとも難しくて、わからないことだらけ。