Java에서 사용자 홈 디렉토리를 찾는 가장 좋은 방법은 무엇입니까?
어려움은 크로스 플랫폼이어야한다는 것입니다. 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
오래된 질문에도 불구하고 나중에 참조 할 수 있도록 남겨 두십시오.
System.getProperty("user.home");
JavaDoc을 참조하십시오 .
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에서 여러분이 실제로 따르는 것은 사용자의 명목상의 "문서"디렉토리라고 생각합니다.
Windows에서 잘 작동하는 것을 원한다면 WinFoldersJava 라는 패키지가있어 Windows의 '특별한'디렉토리를 얻기 위해 기본 호출을 래핑합니다. 자주 사용하며 잘 작동합니다.
대안은 FileUtils.getUserDirectory()
대신 Apache CommonsIO를 사용하는 것입니다 System.getProperty("user.home")
. 동일한 결과를 얻을 수 있으며 시스템 속성을 지정할 때 오타가 발생할 가능성이 없습니다.
프로젝트에 Apache CommonsIO 라이브러리가 이미있을 가능성이 큽니다. 사용자 홈 디렉토리를 얻는 데만 사용하려는 경우 소개하지 마십시오.
'IT story' 카테고리의 다른 글
Swift에서 willSet 및 didSet의 목적은 무엇입니까? (0) | 2020.04.04 |
---|---|
Node.js 웹 애플리케이션에서 MongoDB 연결을 어떻게 관리합니까? (0) | 2020.04.04 |
SQL에서 TRUNCATE와 DELETE의 차이점은 무엇입니까? (0) | 2020.04.04 |
jquery UI 대화 상자 : 제목 표시 줄없이 초기화하는 방법? (0) | 2020.04.04 |
linq 확장 방법을 사용하여 왼쪽 외부 조인을 수행하는 방법 (0) | 2020.04.04 |