有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java更有效地从Jar中提取文件

我正在扩展一个实用程序类,它捆绑了一组图像和图像。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循环绝不是问题的根源;是创建所有输入流的过程减慢了速度)

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) 个答案

  1. # 1 楼答案

    This library可能不会像您需要的那样进行压缩,但会更快

  2. # 2 楼答案

    打开罐子是一项非常昂贵的操作。因此,您可能希望打开JAR一次,并将JarFile实例保存在某个静态字段中。在您的情况下,您还需要读取所有条目并将它们保存在hashmap中,以便即时访问所需的资源

    另一个解决方案是将JAR放在类路径上并使用

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

    当心“/”!如果省略它,Java将在找到DivineFont文件的同一目录(包)中进行搜索。班级

    在Java中,从类路径获取东西已经被优化到了极致

  3. # 3 楼答案

    我找到了答案。我最初问题的答案是“错误的问题”Jar文件不是问题所在,而是我用来加载图像的库

    当我从文件系统加载时,图像被命名为“38.png”,等等。当我从Jar加载时,我只是将其命名为“38”

    库中的图像加载器类使用名称的文件扩展名来标识要使用的图像加载器。如果没有文件扩展名,它将使用较慢的基本图像加载程序。当我改变这一行时:

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

    关于这一行:

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

    我们是赢家

    谢谢你们的帮助,伙计们。我花了几个小时才弄明白这一点,但如果不是因为你的帖子,我可能会继续认为责任在于Java,而不是我正在使用的库

  4. # 4 楼答案

    Jar文件操作可能非常昂贵,Java类库已经实现了这种资源加载(可能尽可能高效)

    另外,一旦您进入webstart,您的jar文件名将被破坏,因此您可能最终不得不浏览类路径上的每个jar文件来加载资源(我已经完成了!丑陋!)

    而是使用Class.getResourceAsStream(String resourceName)。我没有分析它,但我没有注意到它明显比直接文件访问慢