Open Source WEB

バックスラッシュ(\,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 を使おう

というのが良いみたいだ。


戻る:バックスラッシュ(\,5C)の文字化けは直ったか

次へ:〜が~に文字化けするのは直ったか


フィードバック:

Name:
Comment:

There is no comment.

このサイトは、 IPA の「平成15年度オープンソフトウエア活用基盤整備事業」 の委託事業として開発されたKahuaで試験的に運用しております。

Copyright (c) 2004-2007 株式会社タイムインターメディア About Us