Как моя программа Java хранит файлы внутри своего .jar файла?
Я знаю, что .jar файлы - это в основном архивы, а также приложения. Я спрашиваю, как я могу хранить данные (фактические файлы, а не только строки), упакованные внутри моей программы? Я хочу сделать это в своем Java-коде.
Причина этого, если ваше удивление заключается в том, что я создаю серверный мод игры. Сервер запускается и создает все данные уровня, и я хочу сохранить все эти файлы в моем приложении .jar.
Ответы
Ответ 1
Да, вы можете это сделать.
Доступ к ресурсам без кода в JAR файле в пути к классам можно получить с помощью Class.getResourceAsStream(String)
. Приложения обычно делают это, например, для внедрения интернационализированных сообщений в виде пакетов ресурсов.
Чтобы получить файл в JAR файле, просто скопируйте его в нужное место в дереве каталогов ввода, прежде чем запускать команду jar
.
FOLLOW UP
Теоретически ваше приложение может хранить файлы в своем собственном файле JAR при определенных обстоятельствах:
- JAR должен быть файлом в локальной файловой системе; то есть не JAR, который был получен с удаленного сервера.
- Приложение должно иметь доступ на запись к файлу JAR и его родительскому каталогу.
- Приложению не нужно читать файл, который он написал в JAR в текущем загрузчике классов; то есть без выхода и перезапуска.
- JAR не должен быть подписан.
Процедура:
- Найдите файл JAR и откройте его как ZIP-архиватор.
- Создайте запись ZIP-архива для записи новой версии файла JAR.
- Запись файлов приложения в файл.
- Запишите все ресурсы из ZIP-ридера в запись, исключая старые версии файлов приложений.
- Закройте устройство чтения и записи.
- Переименуйте новую версию JAR для замены старого.
Последний шаг может не работать, если начальный JAR заблокирован JVM/OS. В этом случае вам нужно переименовать в обертку script.
Однако, я думаю, что большинство людей согласятся с тем, что это ПЛОХАЯ ИДЕЯ. Это проще и надежнее просто писать обычные файлы.
Ответ 2
Другие ответы предоставили несколько хороших стратегий, но я собираюсь предложить пойти в несколько другом направлении.
Эта игра, предположительно, имеет графику и является настольным приложением. Наиболее легко распространять настольные приложения с веб-сервера.
Если обе эти вещи верны для вашей игры, ознакомьтесь с Java Web Start, чтобы развернуть его.
JWS предлагает API, недоступные для других приложений. и один из них представляет особый интерес для этой проблемы - PersistenceService. PersistenceService позволяет хранить и восстанавливать небольшие объемы данных приложением. (даже если он находится в песочнице). Я сделал небольшую демонстрацию . службы PersistenceService.
Идея заключалась бы в проверке PersistenceService для данных приложения, а если не найдена, используйте данные в Jars. Если пользователь/приложение изменяет данные, напишите измененные данные в PersistenceService.
JWS также предлагает другие приятные функции, такие как заставки, интеграция с настольными системами, автоматические обновления.
Ответ 3
Это невозможно. Однако вы можете искать встроенные базы данных для своего использования. Java 6 поставляется с JavaDB. Если вы не хотите его использовать, вы можете найти здесь http://java-source.net/open-source/database-engines
Ответ 4
Я бы рекомендовал рассмотреть два JAR: один для хранения файлов классов приложений и другого JAR для хранения пользовательских данных. Если у вас нет двух отдельных JAR-серверов, у вас возникнут трудности с получением блокировки записи из операционной системы (поскольку вы пытаетесь перезаписать JAR, содержащий вашу программу, в то время как Java читает его).
Чтобы создать JAR, используйте класс java.util.jar.JarFile. Существует также fooobar.com/questions/61583/..., который описывает, как создать/записать файл JAR.
Ответ 5
Не делай этого. Файл jar является источником классов и ресурсов приложений, а не файловой системы. Вы бы не пытались сохранять файлы в exe, не так ли?
Ответ 6
Создав файл в исходных пакетах (например: /src/resource/file.txt
), его содержимое можно прочитать с помощью Class.getResourceAsStream(String)
Это рабочая реализация следующего answer
InputStream is = Class.class.getResourceAsStream("/resource/file.txt");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
System.out.println(sb.toString());
Ответ 7
Я могу подтвердить, что процедура, описанная Стивеном, действительно работает. Я использую его в течение последних 5 лет с небольшой модификацией, я копирую jar, затем выгружаю классы из оригинальной банки и перезаряжаю классы из новой скопированной банки и делаю модификации оригинальной банки, а затем повторяю процедуру перезагрузки.
Если вы работаете в Unix/Solaris/Unix, у вас нет проблем с блокировкой доступа к jar, поэтому не стоит беспокоиться об этом выше. Однако, если вы собираетесь получать доступ к ресурсам после добавления их в банку, вам нужен этот перезагружающий бизнес.