2

一連の画像と .xml 記述ファイルをバンドルするユーティリティ クラスを拡張しています。現在、すべてのファイルをディレクトリに保持し、そこからロードしています。ディレクトリは次のようになります。

8.png
8.xml
9.png
9.xml
10.png
10.xml
...
...
50.png
50.xml
...



これが私の現在のコンストラクタです。それは電光石火のように速く、必要なことを実行します。(読みやすくするために、エラー チェックの一部を削除しました):

public DivineFont(String directory ) {

    File dir = new File(directory);

    //children is an array that looks like this: '10.fnt', '11.fnt', etc.
    String[] children = dir.list(fntFileFilter);

    fonts = new Hashtable<Integer, AngelCodeFont>(100);

    AngelCodeFont buffer;
    int number;
            String fntFile;
            String imgFile;

    for(int k = 0; k < children.length; k++ ) {
        number = Integer.parseInt( children[k].split("\\.")[0] );
        fntFile = directory + File.separator + number + ".xml";
        imgFile = directory + File.separator + number + ".png";
        buffer = new AngelCodeFont(fntFile, imgFile);

        fonts.put(number, buffer);
    }
}

Webstart とクリーン度のために、代わりに Jar からこれらのリソースをロードしようとしました。動作していますが、読み込み時間が一瞬から数秒になり、許容できません。これが私が試したコードです(ここでも、エラーチェックは削除されています):

(これは私がやりたいことを実行するための最良の方法ではありません。アイデアが機能するかどうかを確認するためのモックアップです。機能しませんでした。2 つの for ループは決して問題の原因ではありません。速度を低下させるすべての InputStreams を作成するプロセス)

public DivineFont(String jarFileName ) {

    JarFile jarfile = new JarFile(jarFileName);
    Enumeration<JarEntry> em = jarfile.entries();
    ArrayList<Integer> fontHeights = new ArrayList<Integer>(100);
    for (Enumeration em1 = jarfile.entries(); em1.hasMoreElements(); ) {
        String fileName = em1.nextElement().toString();
        if( fileName.endsWith(".fnt") ) {
            fontHeights.add( Integer.parseInt(fileName.split("\\.")[0] ) );
        }
    }

    fonts = new Hashtable<Integer, AngelCodeFont>(100);

    AngelCodeFont buffer;
    int number;

    for(int k = 0; k < fontHeights.size(); k++ ) {
        number = fontHeights.get(k);
        InputStream fntFileStream = jarfile.getInputStream(jarfile.getEntry(number + ".xml"));
        InputStream pngFileStream = jarfile.getInputStream(jarfile.getEntry(number + ".png"));
        buffer = new AngelCodeFont(String.valueOf(number), fntFileStream, pngFileStream );

        fonts.put(number, buffer);


    }
}


ここで試した方法以外に、.jar ファイルを操作するより良い方法を知っている人はいますか? これがAngelCodeFont APIです。絶対に必要な場合は、そのためのパッチを提出できますが、提出する必要はありません。私がやりたいことを行う方法がおそらくあるように思えますが、私はそれに慣れていません。

jar を一時ディレクトリにすばやくダンプして、そこからファイルを読み取ることにひどく反対しているわけではありませんが、jar から直接読み取りをすばやく行う方法がある場合は、むしろそれを実行したいと思います。

また、圧縮はまったく問題ではありません。私が瓶を使用している唯一の理由は、梱包の問題です。

4

4 に答える 4

4

JAR を開くことは、非常にコストのかかる操作です。そのため、JAR を一度開いて、JarFileインスタンスをどこかの静的フィールドに保持したい場合があります。あなたの場合、必要なリソースにすぐにアクセスできるように、すべてのエントリを読み取り、それらをハッシュマップに保持することもできます。

別の解決策は、JAR をクラスパスに配置して使用することです。

DivineFont.class.getContextClassLoader().getResource*("/8.png");

「/」に注意してください!これを省略すると、Java は DivineFont.class ファイルを見つけたのと同じディレクトリ (パッケージ) を検索します。

クラスパスからの取得は、Java では死ぬほど最適化されています。

于 2009-02-12T16:33:05.427 に答える
1

さて、私は答えを見つけました。私の最初の質問に対する答えは「間違った質問」でした。Jar ファイルは問題ではなく、画像をロードするために使用していたライブラリでした。

ファイル システムからロードしているときは、画像に「38.png」という名前が付けられていました。Jar からロードしているときは、単純に「38」という名前を付けていました。

ライブラリ内のイメージ ローダー クラスは、名前のファイル拡張子を使用して、使用するイメージ ローダーを識別します。ファイル拡張子がない場合は、低速の基本的なイメージ ローダーが使用されます。この行を変更したとき:

buffer = new AngelCodeFont(String.valueOf(number), fntFileStream, pngFileStream );

この行に:

buffer = new AngelCodeFont( number + ".png", fntFileStream, pngFileStream );

私たち自身が勝者です。

とにかく助けてくれてありがとう。これを理解するのに数時間かかりましたが、あなたの投稿がなければ、私が使用しているライブラリではなく Java のせいだと思い続けていたでしょう。

于 2009-02-14T19:06:07.617 に答える
0

Jar ファイルの操作は非常にコストがかかる可能性があり、Java クラス ライブラリはこの種のリソースの読み込みを既に実装しています (おそらく可能な限り効率的に)。

さらに、webstart に入ると、jar ファイル名が壊れてしまうため、リソースをロードするためにクラスパス上のすべての jar ファイルを調べなければならない可能性があります (私はやった! 醜い!)

代わりに、Class.getResourceAsStream(String resourceName)を使用してください。プロファイリングはしていませんが、ファイルへの直接アクセスよりも著しく遅いことに気づいていません。

于 2009-02-12T17:30:44.537 に答える
-2

このライブラリは必要なだけ圧縮されない可能性がありますが、より高速になります...

于 2009-02-12T16:30:49.847 に答える