6

getResourceAsStreamメソッドは、感嘆符で終わるディレクトリで実行可能 jar を実行すると常に null を返します。

次の例では、次のディレクトリ構造の Eclipse プロジェクトがあります。

src\ (Source Folder)
    main\ (Package)
        Main.java
    res\ (Source Folder)
        images\
            Logo.png

次のように Logo.png を読んでいます。

public static void main(String[] args) throws IOException {
    try (InputStream is = Main.class.getClassLoader().getResourceAsStream("images/Logo.png")) {
        Image image = ImageIO.read(is);
        System.out.println(image);
    }   
}

2 つのテスト ケースについては、添付ファイルを参照してください。まず、実行可能jarがディレクトリ「D:\test123!@#」から問題なく起動されます。次に、実行可能 jar がディレクトリ「D:\test123!@#!!!」から開始されますが、問題があります。

感嘆符で終わるディレクトリはサポートされていませんか? コードが間違っていますか?

前もって感謝します。

! で終わるディレクトリで実行可能 jar を実行するとエラーが発生する

4

2 に答える 2

8

おそらく、このバグまたは Java バグ データベースにある多くの同様のバグのいずれかが原因です。

http://bugs.sun.com/view_bug.do?bug_id=4523159

これは、jar URL 内の「!/」が、JAR ファイル名と JAR 自体内のパスとの間の区切り記号として解釈されるためです。ディレクトリ名が ! で終わる場合、ディレクトリの末尾にある "!/" 文字シーケンスが正しく解釈されません。あなたの場合、実際には次の URL でリソースにアクセスしようとしています。

jar:file:///d:/test1231@#!!!/test.jar!/images/Logo.png

このバグはほぼ 12 年間未解決のままであり、修正される見込みはありません。実際、他のものを壊さずに修正する方法がわかりません。問題は、使用する設計上の決定です。JAR ファイルの URL スキームで特別な意味を持つ文字 (区切り文字) として:

jar:<URL for JAR file>!/<path within the JAR file>

感嘆符は URL で許可されている文字であるため、JAR ファイル自体への URL と JAR ファイル内のパスの両方で感嘆符が使用される場合があり、場合によっては実際の「!/」区切り文字を見つけることができなくなります。 .

于 2013-07-04T09:22:47.667 に答える
1

Windows での簡単な回避策は、パスで「/」の代わりに「\」を使用することです。これは、"!/" 文字シーケンスがフル パスの後にあることを意味します。例えば:

new URL("jar:file:\\d:\\test1231@#!!!\\test.jar!/images/Logo.png");

私のコード:

File jar = new File(jarPath + "/" + jarName);
URL url = new URL("jar:" + jar.toURI() + "!" + dataFilePath);
InputStream stream = null;
try {
    stream = url.openStream();
} catch (FileNotFoundException e) {
    // Windows fix
    URL urlFix = new URL("jar:" + jar.toURI().toString().replace('/', '\\')
        + "!" + dataFilePath);
    stream = urlFix.openStream();
}

toURI() はスペースなどを処理するため、toURI() を使用します。

修正:

修正自体は、Java がファイルが存在するかどうかを確認し、そうでない場合は、セパレーターが使い果たされるまで次のセパレーター (URL の「!/」部分) に進み、例外をスローすることです。したがって、「d:\test1231@#!!」と表示されます。java.io.FileNotFoundException をスローし、存在する "d:\test1231@#!!!\test.jar" を試行します。このように、「!」があっても問題ありません。ファイルパスまたはjarのファイル内。

または、「!/」を、不正なファイル名または特定のもの (「jarpath:」など) に切り替えることもできます。

または、jar のファイル パスに別のパラメーターを使用させます。

ノート:

何かをオーバーライドしたり、ハンドラーを交換したり、コードを変更して最初にファイルを開き、後でjarファイルの中を調べたりすることは可能かもしれませんが、私は見ていません。

于 2015-02-13T19:43:44.437 に答える