我正在尝试存储对我的应用程序属性所做的更改。 .properties
文件位于resources
包中,与包含我的UI和模型的包不同。
我使用以下方式打开了包裹:
this.getClass().getClassLoader().getResourceAsStream("resources/settings.properties")
是否有相应的功能允许我在同一个.Properties文件中持久更改属性类?
答案 0 :(得分:24)
通常,您不能将内容放回到从类加载器获得的资源中:
类加载器资源通常是只读的;即保存在只读文件/只读目录中。
如果您从JAR文件获取资源,则JAR文件不仅可以更新。 (要“更新”,您需要提取旧的JAR内容并使用更新的内容创建一个新的JAR。这与ZIP文件的结构有关...)
在某些情况下,类加载器资源将被动态下载,并且无法将更改推回到您下载的位置。
即使你可以更新从类加载器获得的资源,这也是一个坏主意/坏习惯。
使用用户首选项“干扰”干净的应用程序安装。除此之外,这意味着无法与其他用户共享安装(除非您处理多个用户的首选项...)。
将应用程序安装为可写入存在安全性问题,以便可以更新嵌入式首选项。想想病毒!想一个可能倾向于废弃其他用户偏好的用户!
使用特定于用户的应用程序副本存在管理问题。如果用户必须安装自己的应用程序副本,那么也存在潜在的安全问题。
最后,这不是系统管理员(和受过教育的用户)期望软件行为的方式。最佳做法是以预期的方式处理用户偏好:
对于以Java为中心的解决方案,请使用Java Preferences API。
或者,您可以write a Properties file包含适用于操作系统的用户可写目录的首选项。
在Windows上,您可以使用特定于Windows的API将首选项存储在Windows注册表中(yuck)。
答案 1 :(得分:9)
'resources'包中的,与包含我的UI和模型的包不同。
你应该使用上下文的类加载器。
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
properties.load(classLoader.getResourceAsStream("resources/settings.properties"));
是否有一个功能相当的允许我在同一个.Properties文件中持久更改属性类?
您需要Properties#store()
,这可以是OutputStream
或Writer
。首先,您需要获取属性文件的URL
并获取其URI
,以便为此创建File
,并将其包装在FileOutputStream
中。
URL url = classLoader.getResource("resources/settings.properties");
properties.store(new FileOutputStream(new File(url.toURI())), null);
答案 2 :(得分:5)
当您将应用程序包装为JAR文件时,您的属性文件将是该JAR中的一个(可能是压缩的)文件,尝试写入您自己的JAR是个坏主意。
getResourceAsStream()
用于打开阅读资源,这些资源可以在类路径的任何位置。您无法写入URL或JAR内部,只能写入文件,因此为输出提供相同的API没有意义。
找到一个你可以写入的目录,并在那里写下你的属性。
将属性从安装类路径(可能在JAR中)直接复制到文件(如果它尚不存在),作为应用程序启动时的第一个操作,这可能是个好主意。这将为您提供可以写入的属性文件,但此属性文件的主副本将来自您的项目可交付项。
答案 3 :(得分:2)
听起来您想要存储用户首选项。考虑使用Java Preferences API。
答案 4 :(得分:0)
除了Carl's answer之外,如果您要经常读取和写入此文件,并期望您的应用程序扩展范围,请考虑是否进一步(或几个步骤)进一步使用基于文件的数据库,如SQLite。 SQLite有一些JDBC包装器可以让你超越Java Properties接口提供的基本字符串键值查找。
答案 5 :(得分:0)
虽然将文件写入资源不太实用,但是当我们的应用程序只在IDEA本地运行而没有部署时,我们仍然需要这样做,那么我们可以这样做:
URL resource = Thread.currentThread().getContextClassLoader().getResource("settings.properties");
String path= resource.getPath();
OutputStream outputStream = new FileOutputStream(path);
//outputStream write