![](/img/trans.png)
[英]What's the best way to find the home directory of an arbitrary user in Java?
[英]What is the best way to find the users home directory in Java?
困难在于它应该是跨平台的。 Windows 2000、XP、Vista、OSX、Linux、其他 unix 变体。 我正在寻找可以在所有平台上完成此操作的代码片段,以及一种检测平台的方法。
现在,您应该知道user.home
无法正常工作的错误 4787931 ,因此请不要向我提供教科书的答案,我可以在手册中自己找到这些答案。
您引用的错误(错误 4787391)已在 Java 8 中修复。即使您使用的是旧版本的 Java, System.getProperty("user.home")
方法可能仍然是最好的。 user.home
方法似乎在很多情况下都有效。 Windows 上的 100% 防弹解决方案很难,因为 Windows 对主目录的含义有一个转变的概念。
如果user.home
对您来说不够好,我建议为 windows 选择home directory
的定义并使用它,使用System.getenv(String)
获取适当的环境变量。
实际上使用 Java 8 正确的方法是使用:
System.getProperty("user.home");
错误JDK-6519127已得到修复, 发行说明的“JDK 8 和 JDK 7 之间的不兼容性”部分指出:
区域:核心库/java.lang
概要
用于在 Windows 上确定用户主目录的步骤已更改为遵循 Microsoft 推荐的方法。 在旧版本的 Windows 或注册表设置或环境变量设置为其他目录的情况下,可能会观察到此更改。 不兼容的性质
behavioral RFE 6519127
尽管问题很老,但我将其留作将来参考。
System.getProperty("user.home");
请参阅JavaDoc 。
对于 Windows,HOME 目录的概念似乎有点模糊。 如果环境变量(HOMEDRIVE/HOMEPATH/USERPROFILE) 不够,您可能不得不通过JNI或JNA使用本机函数。SHGetFolderPath允许您检索特殊文件夹,例如我的文档(CSIDL_PERSONAL) 或本地设置\应用程序数据(CSIDL_LOCAL_APPDATA)。
示例 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('\0');
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);
}
}
其他人已经回答了我面前的问题,但是打印出所有可用属性的有用程序是:
for (Map.Entry<?,?> e : System.getProperties().entrySet()) {
System.out.println(String.format("%s = %s", e.getKey(), e.getValue()));
}
当我搜索 Scala 版本时,我只能找到上面 McDowell 的 JNA 代码。 我在这里包括我的 Scala 端口,因为目前没有更合适的地方。
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 != '\0'))
case _ => System.getProperty("user.home")
})
}
}
}
与 Java 版本一样,您需要将Java Native Access (包括 jar 文件)添加到您引用的库中。
很高兴看到 JNA 现在比发布原始代码时更容易做到这一点。
替代方法是使用 Apache CommonsIO FileUtils.getUserDirectory FileUtils.getUserDirectory()
而不是System.getProperty("user.home")
。 它将为您提供相同的结果,并且在指定系统属性时没有机会引入拼写错误。
您的项目中很有可能已经拥有 Apache CommonsIO 库。 如果您打算仅将其用于获取用户主目录,请不要引入它。
我将使用错误报告中详述的算法,使用 System.getenv(String),如果没有环境变量指示有效的现有目录,则回退到使用 user.dir 属性。 这应该可以跨平台工作。
我认为,在 Windows 下,您真正追求的是用户的名义“文档”目录。
如果您想要在 windows 上运行良好的东西,那么有一个名为WinFoldersJava的 package 包装了本机调用以获取 ZAEA23489CE3AA9B6406EBB28E0CDA430 上的“特殊”目录我们经常使用它并且效果很好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.