Создать файл в папке resources / source в java программно? - PullRequest
12 голосов
/ 15 декабря 2011

У меня есть две папки ресурсов.

src - вот мои файлы .java

resources - вот мои файлы ресурсов (изображения, .properties), организованные в папки (пакеты).

Есть ли способ программно добавить другой файл .properties в эту папку ресурсов?

Я пробовал что-то вроде этого:

public static void savePropertiesToFile(Properties properties, File propertiesFile) throws IOException {
        FileOutputStream out = new FileOutputStream(propertiesFile);
        properties.store(out, null);
        out.close();
    }

и до этого создал:

new File("/folderInResources/newProperties.properties");

Но он ищет этот путь в файловой системе. Как заставить его посмотреть в папке ресурсов?

РЕДАКТИРОВАТЬ : Позвольте мне сказать, о чем это. У меня есть приложение с графическим интерфейсом, и я поддерживаю 2 языка (2 файла .properties в папке ресурсов). Теперь я добавил опцию, которая позволяет пользователю легко переводить приложение, и когда он заканчивает, я сохраняю новые свойства .properties на диске в какой-то скрытой папке и считываю их оттуда. Но я надеялся, что смогу сохранить эти новые файлы .properties (новый язык) рядом с текущими языками (папка ресурсов). У меня есть класс статических сообщений, который знает, как загружать ресурсы как с диска, так и с ресурсов по умолчанию в папке ресурсов. Но если пользователь берет этот файл .jar на другом компьютере, у него не будет этих новых языков, поскольку они находятся на диске на этом компьютере, а не внутри файла .jar.

Ответы [ 5 ]

7 голосов
/ 15 декабря 2011

Как уже упоминали другие люди, ресурсы получены через ClassLoader. Тем не менее, эти два ответа не смогли подчеркнуть следующие моменты:

  • ClassLoaders предназначен для абстрактного процесса получения классов и других ресурсов. Ресурс не должен быть файлом в файловой системе; это может быть удаленный URL-адрес или что-либо еще, что вы или кто-либо другой могли бы реализовать, расширив java.lang.ClassLoader.
  • ClassLoaders существует в цепочке дочернего / родительского делегирования. Обычное поведение ClassLoader - сначала попытаться получить ресурс от родителя и только потом искать его собственные ресурсы, но некоторые загрузчики классов делают противоположный порядок (например, в контейнерах сервлетов). В любом случае вам нужно будет определить, в какое место загрузчика классов можно получить материал, в который вы хотите поместить материал, и даже тогда другой загрузчик классов выше или ниже может «украсть» запросы ресурсов вашего клиентского кода.
  • Как указывает Лайонел Порт, даже один ClassLoader может иметь несколько мест, из которых он загружает вещи.
  • ClassLoaders используются для загрузки классов. Если ваша программа может записывать файлы в место, откуда загружаются классы, это может легко стать угрозой безопасности, поскольку пользователь может внедрить код в ваше работающее приложение.

Короткая версия: не делай этого. Напишите более абстрактный интерфейс для концепции «хранилище подобных ресурсам вещей, из которых я могу получить материал», и подынтерфейс для «хранилища подобных ресурсам вещей, из которых я могу получать вещи, но также добавлять вещи из». Реализуйте последний таким образом, чтобы оба использовали ClassLoader.getContextClassLoader().getResource() (для поиска пути к классам) и, в случае сбоя, использовали какой-то другой механизм для получения данных, которые программа могла добавить из некоторого местоположения.

0 голосов
/ 02 февраля 2016

Следующий код записывает в каталог classes вместе с файлами классов.

Как уже отмечали другие, остерегайтесь перезаписи файлов классов.Лучше всего поместить ваши новые файлы в отдельный каталог;однако этот каталог должен уже существовать.Чтобы создать его, создайте подкаталог в ресурсах источника, возможно, содержащий пустой файл.Например, src\main\resources\dir\empty.txt.

public class WriteResource {
    public static void main(String[] args) throws FileNotFoundException {
        String thing = "Text to write to the file";
        String dir = WriteResource.class.getResource("/").getFile();
        //String dir = WriteResource.class.getResource("/dir").getFile();
        OutputStream os = new FileOutputStream(dir + "/file.txt");
        final PrintStream printStream = new PrintStream(os);
        printStream.println(thing);
        printStream.close();
    }
}

Это делает свое дело, но я буду нервничать по поводу развертывания этого вне строго контролируемой среды.Мне не очень нравится идея посторонних лиц, пишущих в мой каталог classes!

0 голосов
/ 14 февраля 2013

Вырежьте основную папку проекта из скомпилированных подпапок ("/ target / classes", "target / test-classes"), и у вас есть базовый путь для восстановления папок вашего проекта с помощью:

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;

public class SubfolderCreator {

public static void main(String... args) throws URISyntaxException, IOException {
    File newResourceFolder = createResourceSubFolder("newFolder");
}

private static File createResourceSubFolder(String folderName) throws URISyntaxException, IOException {
    java.net.URL url = SubfolderCreator.class.getResource("/EXISTING_SUBFOLDER/");
    File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile();
    String projectFolder = fullPathToSubfolder.getAbsolutePath().split("target")[0];
    File testResultsFolder = new File(projectFolder + "src/test/resources/" + folderName);
    if (!testResultsFolder.exists()) {
        testResultsFolder.mkdir();
    }
    return testResultsFolder;
}
}
0 голосов
/ 15 декабря 2011

Проблема может заключаться в том, что путь к классам может содержать несколько корневых каталогов, поэтому различать, какой из них хранить, будет трудно без существующего файла или каталога.

Если загруженный файл уже существует.

File existingFile = ...;
File parentDirectory = existingFile.getParentFile();
new File(parentDirectory, "newProperties.properties");

В противном случае попробуйте получить дескриптор каталога, который, как вы знаете, уникален в вашем каталоге ресурсов.(Не уверен, что это работает)

URL url = this.getClass().getResource("/parentDirectory");
File parentDirectory = new File(new URI(url.toString()));
new File(parentDirectory, "newProperties.properties");
0 голосов
/ 15 декабря 2011

Ресурсы загружаются через загрузчик классов, и загрузчик классов по умолчанию сильно кэшируется.

Вам нужен собственный загрузчик классов с нужным вам поведением для чтения ресурсов из нестатической файловой системы.

...