難点は、クロスプラットフォームであることです。Windows 2000、XP、Vista、OSX、Linux、その他のUNIXバリアント。すべてのプラットフォームでこれを実現できるコードのスニペットと、プラットフォームを検出する方法を探しています。
今、あなたが知っておくべきバグ4787931user.home
正しく動作しませんので、教科書の答えを私に提供しないでください、私はマニュアルでこれらの自分自身を見つけることができます。
難点は、クロスプラットフォームであることです。Windows 2000、XP、Vista、OSX、Linux、その他のUNIXバリアント。すべてのプラットフォームでこれを実現できるコードのスニペットと、プラットフォームを検出する方法を探しています。
今、あなたが知っておくべきバグ4787931user.home
正しく動作しませんので、教科書の答えを私に提供しないでください、私はマニュアルでこれらの自分自身を見つけることができます。
回答:
参照するバグ(バグ4787391)はJava 8で修正されました。古いバージョンのJavaを使用している場合でも、このSystem.getProperty("user.home")
アプローチがおそらく最善です。このuser.home
アプローチは非常に多くのケースで機能するようです。Windowsにはホームディレクトリの意味が変わってきているため、Windowsでの100%防弾ソリューションは難しいです。が十分でない
場合user.home
はhome directory
、Windowsの定義を選択して使用し、で適切な環境変数を取得することをお勧めし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)や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 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バージョンと同様に、両方のjarファイルを含むJava Native Accessを参照ライブラリに追加する必要があります。
元のコードが投稿されたときよりもJNAがこれをはるかに簡単に行えるようになったのは素晴らしいことです。
Windowsでうまく機能するものが必要な場合は、WinFoldersJavaと呼ばれるパッケージがあり、Windowsで「特別な」ディレクトリを取得するためのネイティブ呼び出しをラップします。私たちはそれを頻繁に使用し、それはうまくいきます。