Как скопировать файл в банку за пределы банки?
Я хочу скопировать файл из банки. Файл, который я копирую, будет скопирован вне рабочего каталога. Я проверил несколько тестов и все методы, которые я пытаюсь сделать с 0 байтовыми файлами.
EDIT: я хочу, чтобы копирование файла выполнялось с помощью программы, а не вручную.
Ответы
Ответ 1
Прежде всего, я хочу сказать, что некоторые из ответов, которые были опубликованы ранее, полностью верны, но я хочу дать свое, поскольку иногда мы не можем использовать библиотеки с открытым исходным кодом под GPL или потому, что нам слишком ленив, чтобы скачать jar XD или то, что когда-либо было причиной вашего дела, является автономным решением.
Функция ниже копирует ресурс рядом с файлом Jar:
/**
* Export a resource embedded into a Jar file to the local file path.
*
* @param resourceName ie.: "/SmartLibrary.dll"
* @return The path to the exported resource
* @throws Exception
*/
static public String ExportResource(String resourceName) throws Exception {
InputStream stream = null;
OutputStream resStreamOut = null;
String jarFolder;
try {
stream = ExecutingClass.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
if(stream == null) {
throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
}
int readBytes;
byte[] buffer = new byte[4096];
jarFolder = new File(ExecutingClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
resStreamOut = new FileOutputStream(jarFolder + resourceName);
while ((readBytes = stream.read(buffer)) > 0) {
resStreamOut.write(buffer, 0, readBytes);
}
} catch (Exception ex) {
throw ex;
} finally {
stream.close();
resStreamOut.close();
}
return jarFolder + resourceName;
}
Просто измените ExecutingClass на имя вашего класса и вызовите его следующим образом:
String fullPath = ExportResource("/myresource.ext");
Ответ 2
Учитывая ваш комментарий о 0-байтных файлах, я должен предположить, что вы пытаетесь сделать это программно и, учитывая ваши теги, что вы делаете это на Java. Если это правда, просто используйте Class.getResource(), чтобы получить URL-адрес, указывающий на файл в вашем JAR, тогда Apache Commons IO FileUtils.copyURLToFile(), чтобы скопировать его в файловую систему. Например:.
URL inputUrl = getClass().getResource("/absolute/path/of/source/in/jar/file");
File dest = new File("/path/to/destination/file");
FileUtils.copyURLToFile(inputUrl, dest);
Скорее всего, проблема с любым кодом, который у вас есть сейчас, заключается в том, что вы (правильно) используете буферный выходной поток для записи в файл, но (неправильно) не смогли его закрыть.
О, и вы должны отредактировать свой вопрос, чтобы точно определить, как вы хотите это сделать (программно, а не, язык,...)
Ответ 3
Java 8 (на самом деле FileSystem существует с 1.7) поставляется с некоторыми классными новыми классами/методами для решения этой проблемы. Поскольку кто-то уже упоминал, что JAR в основном ZIP файл, вы можете использовать
final URI jarFileUril = URI.create("jar:file:" + file.toURI().getPath());
final FileSystem fs = FileSystems.newFileSystem(jarFileUri, env);
(См. Почтовый файл)
Затем вы можете использовать один из удобных методов, например:
fs.getPath("filename");
Затем вы можете использовать класс "Файлы"
try (final Stream<Path> sources = Files.walk(from)) {
sources.forEach(src -> {
final Path dest = to.resolve(from.relativize(src).toString());
try {
if (Files.isDirectory(from)) {
if (Files.notExists(to)) {
log.trace("Creating directory {}", to);
Files.createDirectories(to);
}
} else {
log.trace("Extracting file {} to {}", from, to);
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException e) {
throw new RuntimeException("Failed to unzip file.", e);
}
});
}
Примечание. Я попытался распаковать файлы JAR для тестирования
Ответ 4
Более быстрый способ сделать это с помощью Java 7 +, плюс код для получения текущего каталога:
/**
* Copy a file from source to destination.
*
* @param source
* the source
* @param destination
* the destination
* @return True if succeeded , False if not
*/
public static boolean copy(InputStream source , String destination) {
boolean succeess = true;
System.out.println("Copying ->" + source + "\n\tto ->" + destination);
try {
Files.copy(source, Paths.get(destination), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
logger.log(Level.WARNING, "", ex);
succeess = false;
}
return succeess;
}
Тестирование ( icon.png - изображение внутри изображения пакета приложения):
copy(getClass().getResourceAsStream("/image/icon.png"),getBasePathForClass(Main.class)+"icon.png");
О строке кода (getBasePathForClass(Main.class)
): → проверить ответ, который я добавил здесь:) → Получение текущего рабочего каталога в Java
Ответ 5
Используйте JarInputStream класс:
// assuming you already have an InputStream to the jar file..
JarInputStream jis = new JarInputStream( is );
// get the first entry
JarEntry entry = jis.getNextEntry();
// we will loop through all the entries in the jar file
while ( entry != null ) {
// test the entry.getName() against whatever you are looking for, etc
if ( matches ) {
// read from the JarInputStream until the read method returns -1
// ...
// do what ever you want with the read output
// ...
// if you only care about one file, break here
}
// get the next entry
entry = jis.getNextEntry();
}
jis.close();
Смотрите также: JarEntry
Ответ 6
Яйца - это всего лишь zip файл. Разархивируйте его (используя любой удобный вам способ) и скопируйте файл как обычно.
Ответ 7
${JAVA_HOME}/bin/jar -cvf /path/to.jar
Ответ 8
Если вам нужно скопировать его рядом с файлом Jar, вот что делает следующая функция:
/**
* Export a resource embedded into a Jar file to the local file path.
*
* @param resourceName ie.: "/SmartLibrary.dll"
* @return The path to the exported resource
* @throws Exception
*/
static public String ExportResource(String resourceName) throws Exception {//todo move to Utils
InputStream stream = null;
OutputStream resStreamOut = null;
String jarFolder;
try {
stream = OUTFormatReader.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree"
if(stream == null) {
throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
}
int readBytes;
byte[] buffer = new byte[4096];
jarFolder = new File(OUTFormatReader.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
resStreamOut = new FileOutputStream(jarFolder + resourceName);
while ((readBytes = stream.read(buffer)) > 0) {
resStreamOut.write(buffer, 0, readBytes);
}
} catch (Exception ex) {
throw ex;
} finally {
stream.close();
resStreamOut.close();
}
return jarFolder + resourceName;
}
И назовите его следующим образом:
String fullPath = ExportResource("/myresource.ext");
Ответ 9
Чтобы скопировать файл из своей банки, снаружи, вам необходимо использовать следующий подход:
- Получите
InputStream
файл в вашем файле jar с помощью getResourceAsStream()
- Мы открываем целевой файл с помощью
FileOutputStream
- Мы копируем байты из ввода в выходной поток
- Мы закрываем потоки, чтобы предотвратить утечку ресурсов.
Пример кода, который также содержит переменную, чтобы не заменять существующие значения:
public File saveResource(String name) throws IOException {
return saveResource(name, true);
}
public File saveResource(String name, boolean replace) throws IOException {
return saveResource(new File("."), name, replace)
}
public File saveResource(File outputDirectory, String name) throws IOException {
return saveResource(outputDirectory, name, true);
}
public File saveResource(File outputDirectory, String name, boolean replace)
throws IOException {
File out = new File(outputDirectory, name);
if (!replace && out.exists())
return out;
// Step 1:
InputStream resource = this.getClass().getResourceAsStream(name);
if (resource == null)
throw new FileNotFoundException(name + " (resource not found)");
// Step 2 and automatic step 4
try(InputStream in = resource;
OutputStream writer = new BufferedOutputStream(
new FileOutputStream(out))) {
// Step 3
byte[] buffer = new byte[1024 * 4];
int length;
while((length = in.read(buffer)) >= 0) {
writer.write(buffer, 0, length);
}
}
return out;
}