Chat (Lingr.com)
Informaiton
Daily
Column
- MySQL日本語の旅(5/1)
- アクセス向上秘伝(5/9)
- 一風変ったHaskellλ門(6/13)
- SICP Answer Book (5/31) 問題3.26追加
Zope Solution
Extra
アーカイブ
OSS案内所
Site Info
関連リンク
バックスラッシュ(\,5C)が文字化けする と バックスラッシュ(\,5C)が文字化けする(続編) の 2回分も調べて問題が出なかったので、まず大丈夫と思うが、念のため バックスラッシュ(\,5C)が文字化けする(続々編) についても調べる。
比較対象:バックスラッシュ(\,5C)が文字化けする(続々編)
CONVERT()ではどのように変換されるのだろうか
今回は、端末の文字コードはSJIS、そして cp932 の順に指定してみよう。
mysql> SET NAMES sjis; Query OK, 0 rows affected (0.00 sec) mysql> SELECT CONVERT( _sjis 0x5C USING ujis ); +----------------------------------+ | CONVERT( _sjis 0x5C USING ujis ) | +----------------------------------+ | \ | +----------------------------------+ 1 row in set (0.00 sec) mysql> SET NAMES cp932; Query OK, 0 rows affected (0.00 sec) mysql> SELECT CONVERT( _sjis 0x5C USING ujis ); +----------------------------------+ | CONVERT( _sjis 0x5C USING ujis ) | +----------------------------------+ | \ | +----------------------------------+ 1 row in set (0.00 sec)
SELECT文は、どちらもまったく同じである。しかし、SET NAMESで、 sjisを指定した場合と、cp932を指定した場合で結果は異なる。 当然、CONVERT( _sjis 0x5C USING ujis ) は同じで、 16進数では以下のようになる。
mysql> SELECT HEX(CONVERT( _sjis 0x5C USING ujis ) ); +----------------------------------------+ | HEX(CONVERT( _sjis 0x5C USING ujis ) ) | +----------------------------------------+ | 5C | +----------------------------------------+ 1 row in set (0.00 sec)
この関数が返す結果は同じだが、キャラクタセットの環境が異なるので、 再び変換が起きるのである。
その前に、前回の続きである、キャラクタセット間での変換を詳しく調べる ことにしよう。 調べる対象となるキャラクタセットは、 sjis, ujis, cp932, eucjpms, utf8 としよう。 これの全ての組み合わせは、20通りにも及ぶが、 その全てを確認してみた。
HEX(CONVERT( _sjis 0x5C USING ujis ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING cp932 ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING eucjpms ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING utf8 ) ) ⇒ 5C HEX(CONVERT( _ujis 0x5C USING sjis ) ) ⇒ 815F HEX(CONVERT( _ujis 0x5C USING cp932 ) ) ⇒ 5C HEX(CONVERT( _ujis 0x5C USING eucjpms ) ) ⇒ 5C HEX(CONVERT( _ujis 0x5C USING utf8 ) ) ⇒ 5C HEX(CONVERT( _cp932 0x5C USING sjis ) ) ⇒ 815F HEX(CONVERT( _cp932 0x5C USING ujis ) ) ⇒ 5C HEX(CONVERT( _cp932 0x5C USING eucjpms ) ) ⇒ 5C HEX(CONVERT( _cp932 0x5C USING utf8 ) ) ⇒ 5C HEX(CONVERT( _eucjpms 0x5C USING sjis ) ) ⇒ 815F HEX(CONVERT( _eucjpms 0x5C USING ujis ) ) ⇒ 5C HEX(CONVERT( _eucjpms 0x5C USING cp932 ) ) ⇒ 5C HEX(CONVERT( _eucjpms 0x5C USING utf8 ) ) ⇒ 5C HEX(CONVERT( _utf8 0x5C USING sjis ) ) ⇒ 815F HEX(CONVERT( _utf8 0x5C USING ujis ) ) ⇒ 5C HEX(CONVERT( _utf8 0x5C USING cp932 ) ) ⇒ 5C HEX(CONVERT( _utf8 0x5C USING eucjpms ) ) ⇒ 5C
5Cが5Cにならず、2バイトになってしまったのは、いずれも USING の後に sjis を指定した場合である。 つまり、sjisに変換すると、2バイト文字である\(815F)にされてしまう。
これは、上記の ujis, cp932, eucjpms, utf8 だけではなく latin1でも発生 するのであった。
mysql> SELECT HEX(CONVERT( _latin1 0x5C USING sjis ) ); +------------------------------------------+ | HEX(CONVERT( _latin1 0x5C USING sjis ) ) | +------------------------------------------+ | 815F | +------------------------------------------+ 1 row in set (0.00 sec)
\(815F)は何に変換されるか
今度は、sjisの\(815F)を他のキャラクタセットに変換したとき、 何に変換されるかを調べてみよう。
HEX(CONVERT( _sjis 0x815F USING ujis ) ) ⇒ 5C HEX(CONVERT( _sjis 0x815F USING cp932 ) ) ⇒ 5C HEX(CONVERT( _sjis 0x815F USING eucjpms ) ) ⇒ 5C HEX(CONVERT( _sjis 0x815F USING utf8 ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING ujis ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING cp932 ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING eucjpms ) ) ⇒ 5C HEX(CONVERT( _sjis 0x5C USING utf8 ) ) ⇒ 5C
ということは、sjis の 0x815F と 0x5C は、いずれも 他のキャラクタセットに変換したとき 0x5C になってしまうということだ。 要するに、キャラクタ変換の絶対守るべき基本原則である1対1対応が 崩れているのだ。
では、\(0x815F)をsjisではなくcp932とみなすと、どういうことになるか調べてみよう。
mysql> SELECT HEX(CONVERT( _cp932 0x815F USING utf8 ) ); +-------------------------------------------+ | HEX(CONVERT( _cp932 0x815F USING utf8 ) ) | +-------------------------------------------+ | EFBCBC | +-------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT HEX(CONVERT( _utf8 0xEFBCBC USING cp932 ) ); +---------------------------------------------+ | HEX(CONVERT( _utf8 0xEFBCBC USING cp932 ) ) | +---------------------------------------------+ | 815F | +---------------------------------------------+ 1 row in set (0.00 sec)
ということで、utf8との相互変換はうまくいくようだ。
ここで安心してしまうのはまずいかも知れないので、もうちょっと調べてみよう。
HEX(CONVERT( _cp932 0x815F USING sjis ) ) ⇒ 3F (?) HEX(CONVERT( _cp932 0x815F USING ujis ) ) ⇒ 3F (?) HEX(CONVERT( _cp932 0x815F USING eucjpms ) ) ⇒ A1C0 HEX(CONVERT( _cp932 0x815F USING utf8 ) ) ⇒ EFBCBC HEX(CONVERT( _eucjpms 0xA1C0 USING sjis ) ) ⇒ 3F (?) HEX(CONVERT( _eucjpms 0xA1C0 USING ujis ) ) ⇒ 3F (?) HEX(CONVERT( _eucjpms 0xA1C0 USING cp932 ) ) ⇒ 815F HEX(CONVERT( _eucjpms 0xA1C0 USING utf8 ) ) ⇒ EFBCBC HEX(CONVERT( _utf8 0xEFBCBC USING sjis ) ) ⇒ 3F (?) HEX(CONVERT( _utf8 0xEFBCBC USING ujis ) ) ⇒ 3F (?) HEX(CONVERT( _utf8 0xEFBCBC USING cp932 ) ) ⇒ 815F HEX(CONVERT( _utf8 0xEFBCBC USING eucjpms ) ) ⇒ A1C0
3Fは?のことで、要するにそういう変換は出来ないことを示している。 つまり、sjis, ujisへの変換はできないのである。
cp932, eucjpms, utf8を用いたとき、以下の相互変換がきちんと成立している。
_cp932 0x815F ⇔ _eucjpms 0xA1C0 ⇔ _utf8 0xEFBCBC
ということで、
sjis, ujis を捨てて、cp932, eucjpms を使おう
というのが良いみたいだ。
フィードバック:
There is no comment.