萎草の茂るブログ

暇人も多忙の方も。

[Java] クラスの絶対パス名の取得と日本語・記号のデコードの問題

私が Java で書くプログラムでは、クラスの絶対パスを取得する際

クラス名.class.getProtectionDomain().getCodeSource().getLocation().getPath();

或いはそのインスタンスから呼び出す場合は

this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();

のようにしています。しかしこいつが結構な曲者で、例えば

C:\い ろ+は

のようなパス名だった場合、

/C:/%e3%81%84%20%e3%82%8d+%e3%81%af/

のように ASCII にエンコードされてしまいます。もしこれが RFC 3986 に従った

/C:/%e3%81%84+%e3%82%8d%2b%e3%81%af/

というエンコーディングであれば java.net.URLDecoder#decode を用いて容易にデコードできるのですが、どうも微妙に異なる謎のコードになっています。
具体的には

元の文字 RFC 3986 謎のコード
+ %2b +
半角スペース + %20

という違いがあります。
半角スペースは %20 でも特に困りませんが、+ が + の侭では困ってしまいます。

これは + を適切に置換して

path = クラス名.class.getProtectionDomain().getCodeSource().getLocation().getPath().replaceAll("\\+", "%2b");
path = java.net.URLDecoder.decode(path, "UTF-8");

のようにしないと期待した結果が得られないのです。


どうして突然こんなことを書いたかと言うと、拙サイトで公開している Dominion サプライ選択装置でまさにこれに嵌まったからです。
この問題が発覚した経緯は以下の通り:

同ツールの version 2.3 が私の知らぬ間にドミニオンオンラインツールスレにて再配布されていたのですが、そこでこんなレスを見つけました。

178名無しさん:2012/09/20(木) 17:03:06
>>2,57,62,101,112,118,139,141,147,163
ttp://www1.axfc.net/uploader/O/so/218268
暗黒時代を日本語化した
その他色々追加と修正

189名無しさん:2012/10/07(日) 11:23:09
178さんのアップロードしてくれたものを立ち上げると、

ファイルback.pngがありませんとエラーメッセージが表示されて、
アプリが起動しません。
解決方法を知っていらっしゃる方がいましたら、教えて下さい。

190名無しさん:2012/10/07(日) 15:33:25
>>189
起動しないのは DominionSupply.jar か?
これは ttp://nue2004.info/program/dominionsupply/index.htm
ここで配布してる Dominion サプライ選択装置 って奴だな、オンラインツールとは別物
>>178の奴はとにかく何もかも詰め込まれてあるから必要な物だけ自分で選択して使うといいよ

とりあえず DominionSupply.jar が起動できない原因はパス内に + の文字があるからだな
Dominion_Online_2.0.0.2+Setting+Image+ToolTip_20120920 内の + を全部削除すると起動できる

ここで

パス名に記号 + が含まれているとパスの解決に失敗する

というバグに気付いたのです。
当該スレの皆様、ありがとうございました。

尚、このバグは同ツールの version 2.31 で修正しました。