« CD管理データベース・システムで音源をサポートします | メイン | 3日間ハマっていました。 »

2016年2月10日 (水)

音源のサポート、少し時間がかかりそうです

テストを兼ねてCDをリッピングしてテスト環境に音源を設定していたところ、思いがけない問題に行き当たりました。まぁ、問題に行き当たるのは「常に予想外」なんですが・・・。

チャイコフスキーの交響曲第5番のファイル名で問題が起こりました。
Windows Media Player が作ったファイル名の一部(フォルダ名)に
「Tchaikovsky. Sinfonía nº 5 en Mi m, Op. 64」という文字列があったのです。

これの何が問題かというと、
・現システムは CP932 という文字コードで動いています。
・「Tchaikovsky. Sinfonía nº 5 en Mi m, Op. 64」には、CP932 には定義されていない文字が使われています。
なので、現システムでは、この名前の音源ファイルを扱う事ができません。具体的には「音源ファイルが見つからない」というエラーになってしまいます。

回避するのは簡単で、CP932 にない文字を CP932 にある文字に置き換える、削除するなどでOKなんですが、どの文字が CP932 にない文字なのかを見つけるのは大変です。
結局、疑わしい文字を片っ端から置き換えてやってみる事になるのですが、面倒。

Windows の文字セットは CP932 だったのですが、Vista の頃から unicode にも対応していたと思います。
でも、実際のファイル名などで unicode に出くわした事がなかったので、忘れていたんです。

CP932 をやめて UTF8 にすればいいんですけど、これ、面倒な作業になってしまいそうです。
どれほど大変かは調べなくては分かりませんが・・・
----------------------------------------------------------------------------------
以下、テクニカルです。

このシステムは Java で記述していますが、・・・

Java では文字は Unicode で表現されます。Java が Unicode を採用した当初は「1文字は16ビット」だったのですが、その後 Unicode が拡張されて16ビットでは表現できない文字(補助文字)が定義されているのです。
一方、Java で1文字を表す変数型 char はいまだに16ビットのまま。32ビットにしてくれれば良いのだけど、32ビットにすると互換性の問題が起こるんだそうです。そりゃぁそうだ。16ビットだと思って動いているJVMもあるだろうし、そういうのに32ビットデータを渡すとまずいよねぇ。

String などでは UTF16 が使われています。16ビットよりも大きな文字コードは2つに分割して(2文字分の領域を使って)表現されます。
これをサロゲートペアと言います。

このシステムでは出力が HTML なので、HTML で予約された文字はエスケープしなくてはなりません。
また、データベースに書き込む場面でもエスケープが必要です。エスケープするには、「1文字単位での処理」が必要なんですが、
現プログラムではエスケープ不要な文字は直接 Writer に渡して出力しているのです。ところが
javax.servlet.jsp.JspWriter.write(char) はサロゲートペアの片方は受け付けないのです。
char[] か String で出力するしかなさそうです。
という事は、エスケープ不要な文字を出力する場合は「サロゲートペアかどうか」を判断して・・・が必要になるんです。

となると、いきなり出力ではなく StringBuffer か何かに入れておくか・・・。

現プログラムではサロゲートペアが混ざると文字が化けまくるはずです。

サロゲートペアを扱う事自体は難しくはないのですが、面倒。
問題が起こる可能性がある所を洗い出して修正しなくてはならないのですが、かなりの個所を修正する必要がありそうです。
下手すると1週間くらいはかかりそうです。やれやれ。暫くの間は化け文字とお付き合いになりそうです。

コメント

コメントを投稿