在 Java 中查找用户主目录的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/585534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:32:28  来源:igfitidea点击:

What is the best way to find the users home directory in Java?

javacross-platformhome-directory

提问by Bruno Ranschaert

The difficulty is that it should be cross platform. Windows 2000, XP, Vista, OSX, Linux, other unix variants. I am looking for a snippet of code that can accomplish this for all platforms, and a way to detect the platform.

困难在于它应该是跨平台的。Windows 2000、XP、Vista、OSX、Linux、其他 unix 变体。我正在寻找可以为所有平台完成此操作的代码片段,以及一种检测平台的方法。

Now, you should be aware of bug 4787931that user.homedoes not work correctly, so please do not provide me of textbook answers, I can find these myself in the manuals.

现在,你应该知道的错误4787931user.home不能正常工作,所以请不要为我提供教科书的答案,我可以在手册中找到这些我自己。

采纳答案by DJClayworth

The bug you reference (bug 4787391) has been fixed in Java 8. Even if you are using an older version of Java, the System.getProperty("user.home")approach is probably still the best. The user.homeapproach seems to work in a very large number of cases. A 100% bulletproof solution on Windows is hard, because Windows has a shifting concept of what the home directory means.

If user.homeisn't good enough for you I would suggest choosing a definition of home directoryfor windows and using it, getting the appropriate environment variable with System.getenv(String).

您引用的错误(错误 4787391)已在 Java 8 中修复。即使您使用的是旧版本的 Java,该System.getProperty("user.home")方法可能仍然是最好的。这种user.home方法似乎在很多情况下都有效。Windows 上的 100% 防弹解决方案很难,因为 Windows 对主目录的含义有一个不断变化的概念。

如果user.home对您来说还不够好,我建议您选择home directoryfor windows的定义并使用它,使用System.getenv(String).

回答by Joachim Sauer

System.getProperty("user.home");

See the JavaDoc.

请参阅JavaDoc

回答by oxbow_lakes

Others have answered the question before me but a useful program to print out all available properties is:

其他人已经在我之前回答了这个问题,但是打印所有可用属性的有用程序是:

for (Map.Entry<?,?> e : System.getProperties().entrySet()) {
    System.out.println(String.format("%s = %s", e.getKey(), e.getValue())); 
}

回答by McDowell

The concept of a HOME directory seems to be a bit vague when it comes to Windows. If the environment variables(HOMEDRIVE/HOMEPATH/USERPROFILE) aren't enough, you may have to resort to using native functions via JNIor JNA. SHGetFolderPathallows you to retrieve special folders, like My Documents(CSIDL_PERSONAL) or Local Settings\Application Data(CSIDL_LOCAL_APPDATA).

HOME 目录的概念在 Windows 中似乎有点模糊。如果环境变量(HOMEDRIVE/HOMEPATH/USERPROFILE) 不够用,您可能不得不求助于通过JNIJNA使用本机函数。SHGetFolderPath允许您检索特殊文件夹,例如我的文档(CSIDL_PERSONAL) 或本地设置\应用程序数据(CSIDL_LOCAL_APPDATA)。

Sample JNA code:

示例 JNA 代码:

public class PrintAppDataDir {

    public static void main(String[] args) {
        if (com.sun.jna.Platform.isWindows()) {
            HWND hwndOwner = null;
            int nFolder = Shell32.CSIDL_LOCAL_APPDATA;
            HANDLE hToken = null;
            int dwFlags = Shell32.SHGFP_TYPE_CURRENT;
            char[] pszPath = new char[Shell32.MAX_PATH];
            int hResult = Shell32.INSTANCE.SHGetFolderPath(hwndOwner, nFolder,
                    hToken, dwFlags, pszPath);
            if (Shell32.S_OK == hResult) {
                String path = new String(pszPath);
                int len = path.indexOf('
import com.sun.jna.platform.win32._
object jna {
    def getHome: java.io.File = {
        if (!com.sun.jna.Platform.isWindows()) {
            new java.io.File(System.getProperty("user.home"))
        }
        else {
            val pszPath: Array[Char] = new Array[Char](WinDef.MAX_PATH)
            new java.io.File(Shell32.INSTANCE.SHGetSpecialFolderPath(null, pszPath, ShlObj.CSIDL_MYDOCUMENTS, false) match {
                case true => new String(pszPath.takeWhile(c => c != '
System.getProperty("user.home");
')) case _ => System.getProperty("user.home") }) } } }
'); path = path.substring(0, len); System.out.println(path); } else { System.err.println("Error: " + hResult); } } } private static Map<String, Object> OPTIONS = new HashMap<String, Object>(); static { OPTIONS.put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); OPTIONS.put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); } static class HANDLE extends PointerType implements NativeMapped { } static class HWND extends HANDLE { } static interface Shell32 extends Library { public static final int MAX_PATH = 260; public static final int CSIDL_LOCAL_APPDATA = 0x001c; public static final int SHGFP_TYPE_CURRENT = 0; public static final int SHGFP_TYPE_DEFAULT = 1; public static final int S_OK = 0; static Shell32 INSTANCE = (Shell32) Native.loadLibrary("shell32", Shell32.class, OPTIONS); /** * see http://msdn.microsoft.com/en-us/library/bb762181(VS.85).aspx * * HRESULT SHGetFolderPath( HWND hwndOwner, int nFolder, HANDLE hToken, * DWORD dwFlags, LPTSTR pszPath); */ public int SHGetFolderPath(HWND hwndOwner, int nFolder, HANDLE hToken, int dwFlags, char[] pszPath); } }

回答by Lawrence Dol

I would use the algorithm detailed in the bug report using System.getenv(String), and fallback to using the user.dir property if none of the environment variables indicated a valid existing directory. This should work cross-platform.

我将使用 System.getenv(String) 使用错误报告中详述的算法,如果没有环境变量指示有效的现有目录,则回退到使用 user.dir 属性。这应该跨平台工作。

I think, under Windows, what you are really after is the user's notional "documents" directory.

我认为,在 Windows 下,您真正​​想要的是用户名义上的“文档”目录。

回答by Peter

As I was searching for Scala version, all I could find was McDowell's JNA code above. I include my Scala port here, as there currently isn't anywhere more appropriate.

当我在搜索 Scala 版本时,我能找到的只是上面 McDowell 的 JNA 代码。我在这里包括我的 Scala 端口,因为目前没有更合适的地方。

behavioral RFE

6519127

As with the Java version, you will need to add Java Native Access, including both jar files, to your referenced libraries.

与 Java 版本一样,您需要将Java Native Access(包括两个 jar 文件)添加到引用的库中。

It's nice to see that JNA now makes this much easier than when the original code was posted.

很高兴看到 JNA 现在比原始代码发布时更容易。

回答by Paulo Fidalgo

Actually with Java 8 the right way is to use:

实际上对于 Java 8,正确的方法是使用:

behavioral RFE

6519127

The bug JDK-6519127has been fixed and the "Incompatibilities between JDK 8 and JDK 7" section of the release notesstates:

错误JDK-6519127已修复,发行说明的“JDK 8 和 JDK 7 之间的不兼容性”部分指出:

Area: Core Libs / java.lang

Synopsis

The steps used to determine the user's home directory on Windows have changed to follow the Microsoft recommended approach. This change might be observable on older editions of Windows or where registry settings or environment variables are set to other directories. Nature of Incompatibility

##代码##

区域:Core Libs / java.lang

概要

用于在 Windows 上确定用户主目录的步骤已更改为遵循 Microsoft 推荐的方法。在较旧版本的 Windows 或注册表设置或环境变量设置为其他目录的情况下,可能会观察到此更改。不兼容的性质

##代码##

Despite the question being old I leave this for future reference.

尽管这个问题很老,但我还是留了下来以备将来参考。

回答by Neil Benn

If you want something that works well on windows there is a package called WinFoldersJavawhich wraps the native call to get the 'special' directories on Windows. We use it frequently and it works well.

如果你想要一些在 Windows 上运行良好的东西,有一个名为WinFoldersJava的包,它包装了本地调用以获取 Windows 上的“特殊”目录。我们经常使用它,而且效果很好。

回答by mladzo

Alternative would be to use Apache CommonsIO FileUtils.getUserDirectory()instead of System.getProperty("user.home"). It will get you the same result and there is no chance to introduce a typo when specifying system property.

替代方法是使用 Apache CommonsIOFileUtils.getUserDirectory()而不是System.getProperty("user.home"). 它会给你相同的结果,并且在指定系统属性时没有机会引入拼写错误。

There is a big chance you already have Apache CommonsIO library in your project. Don't introduce it if you plan to use it only for getting user home directory.

您的项目中很有可能已经拥有 Apache CommonsIO 库。如果您打算仅使用它来获取用户主目录,请不要引入它。