困难在于它应该是跨平台的.Windows 2000,XP,Vista,OSX,Linux,其他unix版本.我正在寻找可以为所有平台实现此目的的代码片段,以及一种检测平台的方法.
现在,你应该知道的错误4787931是user.home
不能正常工作,所以请不要为我提供教科书的答案,我可以在手册中找到这些我自己.
您引用的错误(错误4787391)已在Java 8中修复.即使您使用的是旧版本的Java,该System.getProperty("user.home")
方法可能仍然是最好的.这种user.home
方法似乎适用于很多案例.Windows上的100%防弹解决方案很难,因为Windows对主目录的含义有一个转变的概念.
如果user.home
对你不够好,我会建议选择home directory
Windows 的定义并使用它,获取适当的环境变量System.getenv(String)
.
实际上使用Java 8正确的方法是使用:
System.getProperty("user.home");
错误JDK-6519127已修复,发行说明中的 "JDK 8和JDK 7之间的不兼容性"部分指出:
区域:Core Libs/java.lang
概要
用于确定Windows上用户主目录的步骤已更改为遵循Microsoft建议的方法.在旧版本的Windows上或注册表设置或环境变量设置为其他目录时,可能会观察到此更改.不相容的性质
behavioral RFE 6519127
尽管问题很老,但我还是留待将来参考.
System.getProperty("user.home");
请参阅JavaDoc.
对于Windows而言,HOME目录的概念似乎有点模糊.如果环境变量(HOMEDRIVE/HOMEPATH/USERPROFILE)不够,则可能不得不求助于通过JNI或JNA使用本机函数.SHGetFolderPath允许您检索特殊文件夹,例如My Documents(CSIDL_PERSONAL)或Local Settings\Application Data(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 MapOPTIONS = new HashMap (); 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现在使此操作变得容易得多。