【问题标题】:Accessing platform-specific application data area访问特定于平台的应用程序数据区
【发布时间】:2014-11-26 08:52:33
【问题描述】:

在 Java 中,我需要找到一种方法在本地存储一些数据,以便在重新启动之间可用。简单的事情,例如窗口位置/大小。我知道这些信息通常存储在 Windows 上的 C:\Users\<username>\AppData 中(通过在 Windows 资源管理器的地址栏中键入 %APPDATA% 访问),但我不知道它在 Mac OS X 上存储在哪里。(作为旁注,我仍然不明白 Windows 上 %APPDATA% 文件夹的结构,以及它的 \Roaming\Local\LocalLow 等子文件夹。)

肯定有一些方法可以将窗口位置等信息存储在这些区域中,具体取决于操作系统。也许甚至已经为执行这些相对普遍的任务而预先构建了一个库?

【问题讨论】:

    标签: java swing storage


    【解决方案1】:

    在 Java 中,我需要找到一种方法在本地存储一些数据,以便在重新启动之间可用。简单的东西,比如窗口 位置/大小。

    我认为Preferences API 适合这个要求。简而言之:

    应用程序需要偏好和配置数据以适应 不同用户和环境的需求。 java.util.prefs 包 为应用程序提供一种存储和检索用户和系统的方法 偏好和配置数据。数据永久存储在 依赖于实现的后备存储。有两个分开的 偏好节点树,一棵用于用户偏好,一棵用于系统 偏好。

    有一个简短而有用的教程here。以下是根据您的要求的一个小示例:

    import java.util.prefs.Preferences;
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class SwingPreferencesTest {
    
        private void createAndShowGUI() {
    
            JTextField dummyTextField = new JTextField(20);
    
            JFrame frame = new JFrame("Demo");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(dummyTextField);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
    
            Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
    
            // Define default values here
            System.out.println("width: " + prefs.getDouble("width", 100d));
            System.out.println("height: " + prefs.getDouble("height", 100d));
            System.out.println("x: " + prefs.getDouble("x", 0d));
            System.out.println("y: " + prefs.getDouble("y", 0d));
    
            // Set new values here
            prefs.putDouble("width", frame.getPreferredSize().getWidth());
            prefs.putDouble("height", frame.getPreferredSize().getHeight());
            prefs.putDouble("x", frame.getLocationOnScreen().getX());
            prefs.putDouble("y", frame.getLocationOnScreen().getY());
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new SwingPreferencesTest().createAndShowGUI();
                }
            });
        }
    }
    

    如果您第一次运行它,您会在控制台中看到首选项默认值:

    width: 100.0
    height: 100.0
    x: 0.0
    y: 0.0
    

    如果您再次运行它,那么这些值将被更新。就我而言:

    width: 240.0
    height: 59.0
    x: 130.0
    y: 130.0
    

    编辑

    根据下面的@Puce 评论,Windows 上的数据存储在注册表中,这是有道理的,因为这是 Windows 用来存储用户/系统/软件数据的方式。您可以在HKEY_CURRENT_USER\JavaSoft\Prefs\[package\class name]下找到示例中生成的注册表项,如下图所示:

    注意:在 Windows 8 x64、JDK 1.7 上测试

    如果您不想使用这些首选项填充注册表,那么您可以只存储应用程序文件夹的路径(与其他应用程序一样)并使用此路径从普通属性文件加载配置数据。继续使用 Preferences(至少存储应用程序的路径)的主要优点是检索/存储配置数据的机制被设计为跨平台,JVM 实现者(而不是开发人员)必须处理实际实现。

    【讨论】:

    • java.util.prefs 不是在 Windows 的注册表中存储东西吗?
    • 这实际上取决于实现。很可能是的,我认为确实如此。 OTOH,它是一种比处理文件/属性更好的存储用户自定义配置的跨平台方式。据我了解,此 API 旨在满足@Puce 问题中提出的主要目的
    • PersistenceService,提到here,是一个替代方案。
    • 感谢该链接,它非常有用!但是,指向 Andrew Thompson 示例的链接似乎不再可用 @trashgod
    • 谢谢@dic19。你的回答非常简洁明了。它没有明确详细说明如何使用该 Preferences 数据设置 JFrame 大小和位置,但我能够在大约一个小时内自行弄清楚。 (我学得很慢。)再次感谢您;你太棒了!
    【解决方案2】:

    您可以将数据存储在

    Paths.get(System.getProperty("user.home")).resolve(".my-application-conf")
    

    或类似的东西。这应该适用于操作系统。

    【讨论】:

    • 但是,"user.home" 不会获取 AppData 或其子目录之一。
    【解决方案3】:

    AFAIK,标准 Java 库中没有解决方案。

    您要么必须找到执行此操作的第 3 方库,要么使用其中一种替代解决方案(请参阅其他答案)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 2011-09-10
      • 2016-05-22
      • 1970-01-01
      • 2011-10-04
      • 2010-11-06
      相关资源
      最近更新 更多