Java - чтение нескольких изображений из одного zip-файла и в конечном итоге превращение их в объекты BufferedImage. Отличная идея? - PullRequest
2 голосов
/ 29 марта 2011

Я работаю над игрой, и мне нужно загрузить несколько файлов изображений (png, gif и т. Д.), Которые я в конечном итоге захочу преобразовать в объекты BufferedImage.В моей настройке я хотел бы загрузить все эти изображения из одного zip-файла "Resources.zip".Этот файл ресурсов будет содержать изображения, файлы карт и аудиофайлы - все они содержатся в различных аккуратно упорядоченных подкаталогах.Я хочу сделать это, потому что (надеюсь) упростит загрузку ресурсов в версиях моей программы и в апплете, и в приложении.Я также надеюсь, что для версии апплета этот метод позволит мне с легкостью показать прогресс загрузки zip-файла игровых ресурсов (который может в конечном итоге составить 10 МБ в зависимости от сложности этой игры, хотя я надеюсь,чтобы сохранить его в таком размере, чтобы он был удобен для браузера).

Я включил свой класс обработки почтовых индексов ниже.Идея в том, что у меня есть отдельный класс обработки ресурсов, и он создает объект 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).

В конце мой вопрос таков:

Это даже хорошая идея?

Есть ли лучший способ загрузить целую кучуФайлы игровых ресурсов в одной загрузке / потоке, в виде апплетов и приложений?

Я приветствую все мысли и предложения!

Спасибо!

Ответы [ 2 ]

1 голос
/ 29 марта 2011

Если вы используете Java-программу, обычно рекомендуется в любом случае связывать ее в виде файла JAR.Так почему бы не поместить ваши классы просто в этот файл jar (в каталогах, конечно).Тогда вы можете просто использовать

`InputStream stream = MayClass.class.getResourceAsStream(imagePath);`

для загрузки данных для каждого изображения, вместо того, чтобы обрабатывать все zip-файлы самостоятельно (и это также работает для jar-файлов, которые на самом деле не находятся в файловой системе, например http-URL).в апплетах).

Я также предполагаю, что jar-файл будет кэширован, но вы должны измерить и сравнить производительность вашего решения с внешним zip-файлом.

1 голос
/ 29 марта 2011

Работа нескольких веб-приложений (например, GWT) с использованием нескольких ресурсов и их помещением в один сжатый файл. Загрузка одного большого файла дешевле, чем нескольких маленьких. Это предполагает, что вы собираетесь использовать все эти ресурсы в вашем приложении. Если нет, то Ленивая загрузка также является жизнеспособной альтернативой.
При этом, как правило, лучше всего заставить приложение работать, а затем профилировать, чтобы найти узкие места. Если нет, у вас будет много сложного кода, и ваше приложение будет работать намного дольше. 10% -20% кода занимает 80-90% времени для выполнения. Вы просто не знаете, какие 10-20%, то есть до тех пор, пока проект в основном не будет завершен.
Если ваша цель - освоить технологии и переделать, то хорошо - хорошо выглядит.

...