我在一个项目中工作,其中有一个大的资源文件夹(结构与数千个小图像)是必需的。客户端希望通过本机安装提供应用程序(包括应用程序运行所需的JVM )。他不想在应用程序中将这些资源打包为文件夹,因为这会在最终用户的硬盘驱动器中创建一个与原始资源一样大的文件夹结构(该文件夹不会占用太多空间,但它有许多小文件),而且只需复制它,文件夹就很容易被窃取。鉴于此,我不能在jar文件中使用资源文件夹打包所有的应用程序,因为我知道jar文件不是可安装的。另一个要求是客户端需要一定的灵活性,以便在已安装的应用程序文件夹结构中添加一些文件,以便为程序添加新功能。因此,安装是(我认为)获得此功能的唯一途径。
我尝试将它们打包到jar文件中,将其包含在构建路径中,并尝试访问它,但即使我通过各种站点进行了所有的研究,我也失败了。尝试了一百万次getResources(),但是不可能在jar文件中获得一个简单的目录,同时从jar文件外的文件夹中获取目录非常容易。我需要访问一个目录,以便获得它包含的文件的列表。
到了这一步。我已经开始问自己,我是否以最好的方式面对这个问题,所以我想问你们所有人:你如何将你需要的资源打包到一个原生java应用程序中,并满足这些要求?
我甚至在考虑创建某种加密过程来创建包含所有信息的单个文件,并在运行时根据需要临时解密它,但我认为有一种更简单、更干净的方法来面对这个问题。
提前谢谢你
编辑:正如您所要求的,我添加了我尝试过的代码:
这是项目结构
project
├───src
│ ├───main
│ │ └───java
│ │ ├───model <--- where my class is
│ │ ├───controllers
│ │ ├───utilities
│ │ └───views
│ ├───resources <--- this is where is (formerly) accessed the content i need
| | ├─── jarfile.jar <--- i've placed file here and included to build path
│ │ └───-various folders and files -
│ └───test
└───target
在jar文件中有软件包src.resources.blalblaba,在这个文件中有我需要的文件夹
Way1:
getResources正在替换jar文件“。使用"/“尝试路径:"src/resources/blablabla/folderINeed”、"src/resources/src/resources/blablabla“(由于可能存在重复)、"folderINeed”、"blablabla/folderINeed“-> URI始终获取NullPointerException,消息为"null”
public void loadContent(String contentPath) throws Exception
{
File resources= null;
File[] listFiles = null;
URI uri = getClass().getClassLoader().getResource(contentPath).toURI();
resources= new File(uri);
listFiles = resources.listFiles();
//do some file proccessing and load them
}
方法2:使用"folderINeed","src/resources/blablabla/folderINeed","blablabla/folderINeed",“../../../资源/blablabla/folderINeed”<- URL返回null,但至少不会引发NullPointerException。
public void loadContent(String contentPath) throws Exception
{
// conseguimos todas las carpetas de animaciones
File resources;
File[] listFiles = null;
URL url = MyClass.class.getResource(contentPath);
if (url == null) {
// error - missing folder
} else {
resources = new File(url.toURI());
listFiles = resources.listFiles();
}
}
方法3:一些使用类JarFile的复杂代码,这些代码对我不起作用,并且面向获取一个简单的文件,而不是一个文件夹。获取的here
发布于 2018-08-02 17:44:30
MY WRONGS:
正如@Joop Egen在他的回答中告诉
我做了什么:
我已经开发了一段代码来读取.jar中的所有文件条目,区分我感兴趣的条目。然后将它们解压缩到应用程序中的一个目录中。通过这样做,我有了对它们的标准访问权限,如果我愿意,我可以简单地在应用程序关闭时删除该目录。我试着直接从jar中使用它们,但是jar文件是压缩文件,所以在某些时刻,内部文件需要从jar中解压到某个地方,就像操作系统处理压缩文件一样。它可以是一个临时目录,也可以不是。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.io.FileUtils;
public class App
{
public static void main(String[] args)
{
try
{
//needed attributes
String pathToJar = "./src/main/blablalba/fileName.jar";
String folderYouWantToRetrieveFromTheJar = "/folderIWant";
String pathOfFilesWithinTheJar="src/resources/blablabla/"+folderYouWantToRetrieveFromTheJar+"/";
String tempDirectoryWhereExtract="./src/main/resources/temp";
//creating the temp directory
File tempDirectoryReference = new File(tempDirectoryWhereExtract);
if (!tempDirectoryReference.exists())
{
Files.createDirectory(tempDirectoryReference.toPath());
}
//searching what entries i need
JarFile jar = new JarFile(pathToJar);
final Enumeration<JarEntry> entries = jar.entries();
List<JarEntry> targetEntries = new ArrayList<>();
while (entries.hasMoreElements())
{
JarEntry entry = entries.nextElement();
//if the entry is what i need
if (entry.getName().startsWith(pathOfFilesWithinTheJar))
{
targetEntries.add(entry);
}
}
//extract every target entry from the .jar
for (JarEntry entry : targetEntries)
{
//in order to copy the structure i will get only the point where folderIWant is present
int index = entry.getName().indexOf(folderYouWantToRetrieveFromTheJar);
String newTemporaryPath = tempDirectoryReference.getPath().toString()+"/"+entry.getName().substring(index);
extractFileFromJar(jar, entry, new File(newTemporaryPath));
}
jar.close();
//(optional) clean after use
FileUtils.deleteDirectory(tempDirectoryReference);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void extractFileFromJar (JarFile jarFile, JarEntry targetEntry, File destinyPath)
{
try
{
if (!destinyPath.getParentFile().exists())
{
createFolderStructure(destinyPath);
}
else
{
Files.createFile(destinyPath.toPath());
}
InputStream inputStream = jarFile.getInputStream(targetEntry);
FileOutputStream outputStream = new java.io.FileOutputStream(destinyPath);
while (inputStream.available() > 0) {
outputStream.write(inputStream.read());
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
private static void createFolderStructure(File destinyPath)
{
File parentPath = destinyPath.getParentFile();
try
{
if (parentPath.exists())
{
Files.createFile(destinyPath.toPath());
}
else
{
Files.createDirectories(destinyPath.getParentFile().toPath());
Files.createFile(destinyPath.toPath());
}
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
发布于 2018-07-26 18:56:23
src/main/java/
是maven的构建约定,所以我假设它就是这样的。
然后,通常会将图像打包为自己的jar中的只读资源,jar是一个单独的maven项目jarfile
。
jarfile/src/main/resources/
将是图像的根目录。例如:jarfile/src/main/resources/icons16/new.png
可以通过下面这样的命令访问:
getClass().getResource("/icons16/new.png"); // Class' package relative path
getClass().getResourceAsStream("/icons16/new.png");
getClassLoader().getResource("icons16/new.png"); // Absolute class path path
在最初的项目中,需要在pom.xml中向jarfile中添加一个dependency
。
如果不使用maven,jarfile.jar必须在类路径上。
File
不能与资源一起使用,但getResourceAsStream通常是可行的。
要读取资源目录,目录路径应该是唯一的,它只是目录资源中的一个文件名列表。
InputStream in = App.class.getResourceAsStream("/icons16");
try (BufferedReader rd = new BufferedReader(new InputStreamReader(in, "UTF-8"))) {
String line;
while ((line = rd.readLine()) != null) {
System.out.println("line: " + line);
}
}
https://stackoverflow.com/questions/51535618
复制相似问题