Java—从单个zip文件中读取多个图像,并最终将它们转换为BuffereImage对象。好主意?

Java—从单个zip文件中读取多个图像,并最终将它们转换为BuffereImage对象。好主意?,java,zip,bufferedimage,bufferedinputstream,Java,Zip,Bufferedimage,Bufferedinputstream,我正在制作一个游戏,我需要加载多个图像文件(png、gif等),最终我会将这些文件转换为BuffereImage对象。在我的设置中,我想从一个zip文件“Resources.zip”加载所有这些图像。该资源文件将包含图像、地图文件和音频文件——所有这些文件都包含在各种有序的子目录中。我之所以想这样做,是因为它(希望)将使我的程序的applet和应用程序版本中的资源加载变得容易。我还希望,对于applet版本,这种方法将使我能够轻松地显示游戏资源zip文件的加载进度(最终可能达到10MB,具体取决

我正在制作一个游戏,我需要加载多个图像文件(png、gif等),最终我会将这些文件转换为BuffereImage对象。在我的设置中,我想从一个zip文件“Resources.zip”加载所有这些图像。该资源文件将包含图像、地图文件和音频文件——所有这些文件都包含在各种有序的子目录中。我之所以想这样做,是因为它(希望)将使我的程序的applet和应用程序版本中的资源加载变得容易。我还希望,对于applet版本,这种方法将使我能够轻松地显示游戏资源zip文件的加载进度(最终可能达到10MB,具体取决于游戏的复杂程度,尽管我希望将其保持在该大小以下,以便浏览器友好)

我在下面介绍了我的拉链处理课程。其思想是,我有一个单独的资源处理类,它创建一个ZipFileHandler对象,用于从resources.zip文件中提取特定资源

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ZipFileHandler
{
private ZipFile zipFile;

public ZipFileHandler(String zipFileLocation)
{
    try
    {
        zipFile = new ZipFile(zipFileLocation);
    }
    catch (IOException e) {System.err.println("Unable to load zip file at location: " + zipFileLocation);}
}

public byte[] getEntry(String filePath)
{
    ZipEntry entry = zipFile.getEntry(filePath);
    int entrySize = (int)entry.getSize();
    try
    {
        BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
        byte[] finalByteArray = new byte[entrySize];

        int bufferSize = 2048;
        byte[] buffer = new byte[2048];
        int chunkSize = 0;
        int bytesRead = 0;

        while(true)
        {
            //Read chunk to buffer
            chunkSize = bis.read(buffer, 0, bufferSize); //read() returns the number of bytes read
            if(chunkSize == -1)
            {
                //read() returns -1 if the end of the stream has been reached
                break;
            }

            //Write that chunk to the finalByteArray
            //System.arraycopy(src, srcPos, dest, destPos, length)
            System.arraycopy(buffer, 0, finalByteArray, bytesRead, chunkSize);

            bytesRead += chunkSize;
        }

        bis.close(); //close BufferedInputStream

        System.err.println("Entry size: " + finalByteArray.length);

        return finalByteArray;
    }
    catch (IOException e)
    {
        System.err.println("No zip entry found at: " + filePath);
        return null;
    }
}
}
我使用ZipFileHandler类如下:

ZipFileHandler zfh = new ZipFileHandler(the_resourceRootPath + "Resources.zip");
    InputStream in = new ByteArrayInputStream(zfh.getEntry("Resources/images/bg_tiles.png"));

    try
    {
        BufferedImage bgTileSprite = ImageIO.read(in);
    }
    catch (IOException e)
    {
        System.err.println("Could not convert zipped image bytearray to a BufferedImage.");
    }
好消息是,它起作用了

但我觉得可能有更好的方法来完成我正在做的事情(而且我对BufferedInputStreams的工作还比较陌生)

最后,我的问题是:

这是个好主意吗

有没有更好的方法可以在一个下载/流中以小程序和应用程序友好的方式加载一整套游戏资源文件

我欢迎所有的想法和建议


谢谢

获取多个资源并将其放在一个压缩文件中是多个web应用程序的工作方式(即GWT)。加载一个大文件比加载多个小文件成本更低。这假设您将使用应用程序中的所有这些资源。如果不是,延迟加载也是一种可行的选择。
也就是说,通常最好是让应用程序正常工作,然后通过分析找出瓶颈所在。如果不是这样,你最终会得到很多复杂的代码,你需要花更长的时间才能让你的应用程序正常工作。10%-20%的代码需要80-90%的时间来执行。你只是不知道;在项目基本完成之前,我不知道那是10-20%。

如果你的目标是学习技术和修补程序,那么做得好-看起来不错。

如果你使用的是Java程序,通常认为最好还是将其打包为jar文件。那么,为什么不将您的类简单地放在这个jar文件中(当然是在目录中)。然后你可以简单地使用

`InputStream stream = MayClass.class.getResourceAsStream(imagePath);`
加载每个图像的数据,而不必自己处理所有zip文件(它也适用于文件系统中没有的jar,例如applet中的httpurl)


我还假设jar将被缓存,但您应该测量并比较性能与使用外部zip文件的解决方案。

我认为您很好地解决了所有zip/输入流问题!谢谢我很高兴它真的起作用了,哈哈。希望其他人也能从中受益。我要指出的一点是,压缩/解压缩将是CPU密集型的,而且图像并不总是能够很好地压缩。请检查zip文件的大小是否比解压缩文件的大小足够小,如果差异不大,你可能想把所有东西连接起来而不是拉拉链。好主意,谢谢。幸运的是,我认为压缩确实有很大的不同,至少对于我的许多压缩文本文件和一些在精灵周围有大量透明空间的图像文件。除了文件压缩之外,还有连接,您是否建议使用类似于一个大型二进制文件的方法,将其读入字节数组,然后使用类似System.arraycopy()的方法拆分?好主意!我只需要找到一个很好的方法来跟踪每个文件的长度。谢谢你的回复!问题是,我希望避免将资源文件放在必须完全加载的同一个文件中,然后才能向用户显示任何内容。如果它是一个10MB的jar文件,您知道有没有一种简单的方法来进行预加载(显示“…80%…”…81%…”之类的内容?我在过去使用过Flash,预加载程序很大,但我对java世界也不太了解。你可以使用多个JAR,然后从清单文件的第一个JAR引用它们。还可以看看JARDINDEX。好消息是,我确实计划使用我正在加载的所有文件。这是几个文件的混合大型平铺精灵表文件、一些角色精灵文件和大量xml映射文件。事实上,我刚刚加载了xml映射文件,所以现在一切都很好!我只是希望我没有做一些我以后会后悔的事情,呵呵。但正如你所注意到的,我的另一个目标是学习和修补!这个项目只是为了好玩不管怎样。:)哦!关于评测:现在,我不确定我该如何评测这个。这在一开始是一次性加载的,我想最后,这取决于在没有这个zip方法的情况下我可以多么容易地进行预加载(比如说,与主jar中的文件相比)。不管怎样,我觉得能够显示加载状态很重要。