Как моя программа 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, поэтому не стоит беспокоиться об этом выше. Однако, если вы собираетесь получать доступ к ресурсам после добавления их в банку, вам нужен этот перезагружающий бизнес.