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 加载这些资源。我已经让它工作了,但是加载时间从瞬间变成了几秒钟,这是不可接受的。这是我尝试过的代码(再次,错误检查被剥离):

(这不是做我想做的事情的最好方法,它是一个模型,看看这个想法是否有效。它没有。两个 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 回答