5

In Java, I need to find a way to store some data locally so that it is available between reboots. Simple things, such as window location/size. I know that such information is usually stored in C:\Users\<username>\AppData on Windows (accessed by typing %APPDATA% in the address bar of Windows Explorer), but I have no idea where it is stored on Mac OS X. (As a side note, I still don't understand the structure of that %APPDATA% folder on Windows, with its \Roaming, \Local, \LocalLow, etc. subfolders.)

Surely there is some way for information like window location to be stored in these areas depending on the OS. Perhaps there is even an library already pre-built for doing these relatively ubiquitous tasks?

halfer
  • 19,824
  • 17
  • 99
  • 186
Sturm
  • 689
  • 2
  • 23
  • 52

3 Answers3

2

In Java, I need to find a way to store some data locally so that it is available between reboots. Simple things, such as window location/size.

I think Preferences API suits this requirement. In a nutshell:

Applications require preference and configuration data to adapt to the needs of different users and environments. The java.util.prefs package provides a way for applications to store and retrieve user and system preference and configuration data. The data is stored persistently in an implementation-dependent backing store. There are two separate trees of preference nodes, one for user preferences and one for system preferences.

There is a short yet useful tutorial here. And here is a little example based on your requirements:

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();
            }
        });
    }
}

If you run it the first time you'll see the preferences default values in console:

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

If you run it again then these values are updated. In my case:

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

Edit

As per @Puce comment below, on Windows data is stored in the registry and it makes sense because it's the way that Windows uses to store user/system/software data. You can find the registry entry generated in the example under HKEY_CURRENT_USER\JavaSoft\Prefs\[package\class name] as shown in picture below:

enter image description here

Note: tested on Windows 8 x64, JDK 1.7

If you don't want to fill the registry with these preferences, then you can just store a path to your application folder (as other applications do) and use this path to load config data from plain properties files. The main advantage to keep using Preferences (at least to store the application's path) is the mechanism to retrieve/store config data is designed to be cross-platform and JVM implementers (not developers) are who have to deal with the actual implementation.

dic19
  • 17,821
  • 6
  • 40
  • 69
  • Doesn't java.util.prefs store things in the Registery on Windows? – Puce Oct 01 '14 at 14:09
  • 1
    It's up to the implementation actually. Most likely yes, I think it does. OTOH it's a cross-platform way to store user custom config better than dealing with files/properties. As far as I understand it this API is designed to the main purpose asked in the question @Puce – dic19 Oct 01 '14 at 14:12
  • 1
    `PersistenceService`, mentioned [here](http://stackoverflow.com/a/6886694/230513), is an alternative. – trashgod Oct 01 '14 at 20:06
  • 1
    Thanks for that link, it's quite useful! However the link to Andrew Thompson's example seems no longer available @trashgod – dic19 Oct 01 '14 at 20:40
  • Thanks, @dic19. Your answer was very clear and concise. It didn't explicitly detail how to set a JFrame size & location with that Preferences data, but I was able to figure it out on my own in about an hour. (I'm a slow learner.) Thank you again; you're awesome! – Sturm Nov 11 '14 at 17:15
0

You could store the data in

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

or something similar. That should work across OSes.

assylias
  • 321,522
  • 82
  • 660
  • 783
0

AFAIK, there is no solution for this in the standard Java library.

You would either have to find a 3rd-party library, which does this, or use one of the alternative solutions (see other answers).

Puce
  • 37,247
  • 13
  • 80
  • 152