어려움은 크로스 플랫폼이어야한다는 것입니다. Windows 2000, XP, Vista, OSX, Linux 및 기타 유닉스 변형. 모든 플랫폼 에서이 작업을 수행 할 수있는 코드 스 니펫과 플랫폼을 감지하는 방법을 찾고 있습니다.
이제, 당신이 알고 있어야 버그 4787931 그 user.home때문에 교과서 답변의 저를 제공하지 마십시오, 제대로 작동하지 않습니다, 나 자신은 매뉴얼에서이를 찾을 수 있습니다.
답변
참조하는 버그 (버그 4787391)는 Java 8에서 수정되었습니다. 이전 버전의 Java를 사용하더라도이 System.getProperty("user.home")방법이 여전히 가장 좋습니다. 이 user.home접근법은 매우 많은 경우에 효과가있는 것 같습니다. Windows에는 홈 디렉토리의 의미에 대한 변화하는 개념이 있기 때문에 Windows의 100 % 방탄 솔루션은 어렵습니다. 충분하지 않은
경우 Windows user.home에 home directory대한 정의를 선택 하고 사용하여 적절한 환경 변수를 사용 하는 것이 좋습니다 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
오래된 질문에도 불구하고 나중에 참조 할 수 있도록 남겨 두십시오.
답변
답변
HOME 디렉토리의 개념은 Windows와 관련하여 약간 모호한 것 같습니다. 경우 환경 변수 (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 코드 만 찾을 수있었습니다. 현재 더 적절한 곳이 없기 때문에 여기에 스칼라 포트를 포함시킵니다.
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가 이제 원래 코드를 게시 할 때보 다 훨씬 쉽게 처리 할 수 있다는 것을 알게되어 기쁩니다.
답변
System.getenv (String)를 사용하여 버그 보고서에 자세히 설명 된 알고리즘을 사용하고 유효한 기존 디렉토리를 나타내는 환경 변수가 없으면 user.dir 속성을 사용하여 대체합니다. 이것은 크로스 플랫폼에서 작동합니다.
Windows에서 여러분이 실제로 따르는 것은 사용자의 명목상의 “문서”디렉토리라고 생각합니다.
