我的 Java 程序如何在其 .jar 文件中存储文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4056682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can my Java program store files inside of its .jar file?
提问by liamzebedee
I know that .jar files are basically archives as well as being applications. What I'm asking is how can I store data(actual files not just strings) packed inside my program? I want to do this within my Java code.
我知道 .jar 文件基本上是档案以及应用程序。我要问的是如何存储打包在我的程序中的数据(实际文件而不仅仅是字符串)?我想在我的 Java 代码中执行此操作。
The reason for this if your wondering is that I'm producing a server mod of a game. The server starts and creates all the level data and I want to store all these file inside my .jar app.
如果您想知道,这样做的原因是我正在制作游戏的服务器模组。服务器启动并创建所有关卡数据,我想将所有这些文件存储在我的 .jar 应用程序中。
采纳答案by Stephen C
Yes you cando this.
是的,你可以这样做。
Non-code resources in a JAR file on the classpath can be access using Class.getResourceAsStream(String)
. Applications routinely do this, for example, to embed internationalized messages as resource bundles.
可以使用 .jar 访问类路径上 JAR 文件中的非代码资源Class.getResourceAsStream(String)
。应用程序通常会这样做,例如,将国际化消息作为资源包嵌入。
To get your file into the JAR file, just copy it into the appropriate place in the input directory tree before you run the jar
command.
要将文件放入 JAR 文件,只需在运行jar
命令之前将其复制到输入目录树中的适当位置即可。
FOLLOW UP
跟进
In theory, your application couldstore files inside its own JAR file, under certain circumstances:
理论上,在某些情况下,您的应用程序可以将文件存储在其自己的 JAR 文件中:
- The JAR has to be a file in the local file system; i.e. not a JAR that was fetched from a remote server.
- The application has to have write access to the JAR file and its parent directory.
- The application must not need to read back the file it wrote to the JAR in the current classloader; i.e. without exiting and restarting.
- The JAR must not need to be be signed.
- JAR 必须是本地文件系统中的文件;即不是从远程服务器获取的 JAR。
- 应用程序必须具有对 JAR 文件及其父目录的写访问权限。
- 应用程序一定不需要读回它在当前类加载器中写入 JAR 的文件;即没有退出和重新启动。
- JAR 必须不需要签名。
The procedure would be:
程序是:
- Locate the JAR file and open as a ZIP archive reader.
- Create a ZIP archive writer to write a new version of JAR file.
- Write the application's files to the writer.
- Write all resources from the ZIP reader to the writer, excluding old versions of the applications files.
- Close the reader and writer.
- Rename the new version of the JAR to replace the old one.
- 找到 JAR 文件并作为 ZIP 存档阅读器打开。
- 创建一个 ZIP 归档编写器来编写新版本的 JAR 文件。
- 将应用程序的文件写入编写器。
- 将 ZIP 读取器中的所有资源写入写入器,不包括旧版本的应用程序文件。
- 关闭读取器和写入器。
- 重命名新版本的 JAR 以替换旧版本。
The last step might not work if the initial JAR is locked by the JVM / OS. In that case, you need do the renaming in a wrapper script.
如果初始 JAR 被 JVM/OS 锁定,最后一步可能不起作用。在这种情况下,您需要在包装脚本中进行重命名。
However, I think that most people would agree that this is a BAD IDEA. It is simpler and more robust to just write regular files.
但是,我认为大多数人都会同意这是一个糟糕的想法。只编写常规文件更简单、更健壮。
回答by Aravind Yarram
This is not possible. You however can look into embedded databases for your usecase. Java 6 comes with JavaDB. If you doesn't want to use it then you can find more here http://java-source.net/open-source/database-engines
这不可能。但是,您可以针对您的用例查看嵌入式数据库。Java 6 带有 JavaDB。如果你不想使用它,那么你可以在这里找到更多http://java-source.net/open-source/database-engines
回答by David-Zazeski
I would recommend that you consider having two JARs: one to store your application's class files and another JAR to store the user data. If you do not have two separate JARs, then you will have difficulties obtaining a write lock from the Operating System (since you would be trying to overwrite the JAR containing your program while java is reading it).
我建议您考虑使用两个 JAR:一个用于存储应用程序的类文件,另一个用于存储用户数据。如果您没有两个单独的 JAR,那么您将难以从操作系统获得写锁(因为您会在 java 读取程序时试图覆盖包含您的程序的 JAR)。
To create a JAR, use the java.util.jar.JarFile class. There is also another question on stackoverflowwhich describes how to create/write a JAR file.
要创建 JAR,请使用java.util.jar.JarFile 类。stackoverflow 上还有另一个问题,它描述了如何创建/编写 JAR 文件。
回答by Andrew Thompson
The other answers have provided some good strategies, but I am going to suggest going in a somewhat different direction.
其他答案提供了一些很好的策略,但我将建议朝着不同的方向前进。
This game supposedly has graphics and is a desktop application. It is most easy to distribute desktop applications from a web server.
这个游戏据说有图形,是一个桌面应用程序。从 Web 服务器分发桌面应用程序是最容易的。
If both those things are true of your game, then look into using Java Web Startto deploy it.
如果您的游戏符合这两点,那么考虑使用Java Web Start来部署它。
JWS offers APIs not available to other apps. & one of particular interest to this problem is the PersistenceService. The PersistenceService allows for small amounts of data to be stored and restored by an app. (even when it is in a sand-box). I have made a small demo. of the PersistenceService.
JWS 提供其他应用程序不可用的 API。对此问题特别感兴趣的一个是 PersistenceService。PersistenceService 允许应用程序存储和恢复少量数据。(即使它在沙箱中)。我做了一个小演示。的 PersistenceService。
The idea would be to check the PersistenceService for the application data, and if not found, use the data in the Jars. If the user/application alters the data, write the altered data to the PersistenceService.
这个想法是检查 PersistenceService 中的应用程序数据,如果没有找到,则使用 Jars 中的数据。如果用户/应用程序更改了数据,则将更改后的数据写入 PersistenceService。
JWS also offers other nice features like splash screens, desktop integration, automatic updates..
JWS 还提供其他不错的功能,如启动画面、桌面集成、自动更新......
回答by user207421
Don't do this. A jar file is a source of application classes and resources, not a file system. You wouldn't try to save files into a exe, would you?
不要这样做。jar 文件是应用程序类和资源的来源,而不是文件系统。您不会尝试将文件保存到 exe 中,对吗?
回答by user2601995
By creating a file in the Source Packages (ex: /src/resource/file.txt
) its contents can be read using Class.getResourceAsStream(String)
通过在源包(例如:)中创建一个文件,/src/resource/file.txt
它的内容可以使用Class.getResourceAsStream(String)
This is a working implementation of the following 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());