Java OutputStream等效于getClass()。getClassLoader()。getResourceAsStream()

时间:2010-01-08 22:33:46

标签: java swing file-io properties persistence

我正在尝试存储对我的应用程序属性所做的更改。 .properties文件位于resources包中,与包含我的UI和模型的包不同。

我使用以下方式打开了包裹:

this.getClass().getClassLoader().getResourceAsStream("resources/settings.properties")

是否有相应的功能允许我在同一个.Properties文件中持久更改属性类?

6 个答案:

答案 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(),这可以是OutputStreamWriter。首先,您需要获取属性文件的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