Find place for dedicated application folder
I'm sorry if this title is badly named, I can't think of a better way to phrase it and so edits would be welcomed.
Most applications I've seen that require hard drive file storage create a folder in a suitable place depending on the operating system. On Windows these folders lie in \Users\[current user]\AppData\[etc], on Mac these folders lie in /Users/[current user]/Library/Application Support/[etc], Ubuntu has a similar thing that I can't think of right now.
I would like to know, how are these file paths consistently found in differing operating systems with different users, and is there, at least in java, a simple way to achieve this?
Thank you.
There should be, but there isn't. I even submitted a bug/RFE about it, but as far as I know, it was never accepted. Here's what I use:
public class ApplicationDirectories {
private static final Logger logger =
Logger.getLogger(ApplicationDirectories.class.getName());
private static final Path config;
private static final Path data;
private static final Path cache;
static {
String os = System.getProperty("os.name");
String home = System.getProperty("user.home");
if (os.contains("Mac")) {
config = Paths.get(home, "Library", "Application Support");
data = config;
cache = config;
} else if (os.contains("Windows")) {
String version = System.getProperty("os.version");
if (version.startsWith("5.")) {
config = getFromEnv("APPDATA", false,
Paths.get(home, "Application Data"));
data = config;
cache = Paths.get(home, "Local Settings", "Application Data");
} else {
config = getFromEnv("APPDATA", false,
Paths.get(home, "AppData", "Roaming"));
data = config;
cache = getFromEnv("LOCALAPPDATA", false,
Paths.get(home, "AppData", "Local"));
}
} else {
config = getFromEnv("XDG_CONFIG_HOME", true,
Paths.get(home, ".config"));
data = getFromEnv("XDG_DATA_HOME", true,
Paths.get(home, ".local", "share"));
cache = getFromEnv("XDG_CACHE_HOME", true,
Paths.get(home, ".cache"));
}
}
/** Prevents instantiation. */
private ApplicationDirectories() {
}
/**
* Retrieves a path from an environment variable, substituting a default
* if the value is absent or invalid.
*
* @param envVar name of environment variable to read
* @param mustBeAbsolute whether enviroment variable's value should be
* considered invalid if it's not an absolute path
* @param defaultPath default to use if environment variable is absent
* or invalid
*
* @return environment variable's value as a {@code Path},
* or {@code defaultPath}
*/
private static Path getFromEnv(String envVar,
boolean mustBeAbsolute,
Path defaultPath) {
Path dir;
String envDir = System.getenv(envVar);
if (envDir == null || envDir.isEmpty()) {
dir = defaultPath;
logger.log(Level.CONFIG,
envVar + " not defined in environment"
+ ", falling back on \"{0}\"", dir);
} else {
dir = Paths.get(envDir);
if (mustBeAbsolute && !dir.isAbsolute()) {
dir = defaultPath;
logger.log(Level.CONFIG,
envVar + " is not an absolute path"
+ ", falling back on \"{0}\"", dir);
}
}
return dir;
}
/**
* Returns directory where the native system expects an application
* to store configuration files for the current user. No attempt is made
* to create the directory, and no checks are done to see if it exists.
*
* @param appName name of application
*/
public static Path configDir(String appName)
{
return config.resolve(appName);
}
/**
* Returns directory where the native system expects an application
* to store implicit data files for the current user. No attempt is made
* to create the directory, and no checks are done to see if it exists.
*
* @param appName name of application
*/
public static Path dataDir(String appName)
{
return data.resolve(appName);
}
/**
* Returns directory where the native system expects an application
* to store cached data for the current user. No attempt is made
* to create the directory, and no checks are done to see if it exists.
*
* @param appName name of application
*/
public static Path cacheDir(String appName)
{
return cache.resolve(appName);
}
}
Some notes:
I'm not sure the code for older Windows versions is even necessary, as Java 8 doesn't run on Windows XP.
The XDG Directory Specification says “All paths set in these environment variables must be absolute. If an implementation encounters a relative path in any of these variables it should consider the path invalid and ignore it.”
The directory can be found with the method
static String defaultDirectory() {
String os = System.getProperty("os.name").toLowerCase();
if (OS.contains("win"))
return System.getenv("APPDATA");
else if (OS.contains("mac"))
return System.getProperty("user.home") + "/Library/Application Support";
else if (OS.contains("nux"))
return System.getProperty("user.home");
else
return System.getProperty("user.dir");
}
It is worth noting that on Linux any such folders should be hidden by beginning their name with .
(Answer found from users CodeBunny and Denis Tulskiy on this post)