it-swarm.com.de

Was ist der beste Weg, um das Home-Verzeichnis der Benutzer in Java zu finden?

Die Schwierigkeit ist, dass es plattformübergreifend sein sollte. Windows 2000, XP, Vista, OSX, Linux und andere Unix-Varianten. Ich suche nach einem Codeausschnitt, der dies für alle Plattformen ermöglicht, und eine Möglichkeit, die Plattform zu erkennen.

Nun sollten Sie wissen, dass Fehler 4787931 dass user.home nicht korrekt funktioniert. Geben Sie mir daher bitte keine Lehrbuchantworten.

218

Der Fehler, auf den Sie sich beziehen (Fehler 4787391), wurde in Java 8 behoben. Selbst wenn Sie eine ältere Java-Version verwenden, ist der System.getProperty("user.home")-Ansatz wahrscheinlich immer noch der beste. Der user.home-Ansatz scheint in einer sehr großen Anzahl von Fällen zu funktionieren. Eine 100% ige kugelsichere Lösung für Windows ist hart, da Windows ein verändertes Konzept für das Ausgangsverzeichnis hat.

Wenn user.home nicht gut genug für Sie ist, würde ich vorschlagen, eine Definition von home directory für Windows zu wählen und zu verwenden, indem Sie die entsprechende Umgebungsvariable mit System.getenv(String) abrufen.

294
DJClayworth

Eigentlich mit Java 8 ist der richtige Weg:

System.getProperty("user.home");

Der Fehler JDK-6519127 wurde behoben und der Abschnitt "Inkompatibilitäten zwischen JDK 8 und JDK 7" der Versionshinweise besagt:

Bereich: Core Libs/Java.lang

Zusammenfassung

Die Schritte, die zum Ermitteln des Basisverzeichnisses des Benutzers unter Windows verwendet wurden, wurden geändert, um dem von Microsoft empfohlenen Ansatz zu folgen. Dieser Wandel ist möglicherweise auf älteren Editionen von Windows oder der Registrierung Einstellungen oder Umgebungsvariablen werden auf andere Verzeichnisse gesetzt. Natur der Unvereinbarkeit

behavioral RFE

6519127

Obwohl die Frage alt ist, lasse ich dies zum Nachschlagen.

111
Paulo Fidalgo

Das Konzept eines HOME-Verzeichnisses scheint in Bezug auf Windows etwas vage zu sein. Wenn die mgebungsvariablen (HOMEDRIVE/HOMEPATH/USERPROFILE) nicht ausreichen, müssen Sie möglicherweise native Funktionen über JNI oder JNA) VERWENDEN . SHGetFolderPath ermöglicht das Abrufen spezieller Ordner wie Eigene Dateien (CSIDL_PERSONAL) oder Lokal Einstellungen\Anwendungsdaten (CSIDL_LOCAL_APPDATA).

JNA-Beispielcode:

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);

    }

}
28
McDowell
System.getProperty("user.home");

Siehe JavaDoc .

25
Joachim Sauer

Andere haben die Frage vor mir beantwortet, aber ein nützliches Programm zum Ausdrucken aller verfügbaren Eigenschaften ist: 

for (Map.Entry<?,?> e : System.getProperties().entrySet()) {
    System.out.println(String.format("%s = %s", e.getKey(), e.getValue())); 
}
15
oxbow_lakes

Als ich nach Scala-Version suchte, konnte ich nur McDowells JNA-Code finden. Ich füge hier meinen Scala-Port hinzu, da es momentan nirgendwo geeigneter ist.

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")
            })
        }
    }
}

Wie bei der Java-Version müssen Sie Java Native Access , einschließlich der beiden JAR-Dateien, Ihren referenzierten Bibliotheken hinzufügen.

Es ist schön zu sehen, dass JNA das jetzt viel einfacher macht, als wenn der Originalcode veröffentlicht wurde.

4
Peter

Ich würde den im Fehlerbericht beschriebenen Algorithmus mithilfe von System.getenv (String) und die Verwendung der user.dir -Eigenschaft verwenden, wenn keine der Umgebungsvariablen ein gültiges vorhandenes Verzeichnis angibt. Dies sollte plattformübergreifend funktionieren.

Ich denke, unter Windows streben Sie nach dem fiktiven Verzeichnis "Dokumente" des Benutzers.

2
Lawrence Dol

Wenn Sie etwas wollen, das unter Windows gut funktioniert, gibt es ein Paket namens WinFoldersJava , das den systemeigenen Aufruf umschließt, um die 'speziellen' Verzeichnisse unter Windows zu erhalten. Wir benutzen es häufig und es funktioniert gut.

0
Neil Benn

Eine Alternative wäre die Verwendung von Apache CommonsIO FileUtils.getUserDirectory() anstelle von System.getProperty("user.home"). Dadurch erhalten Sie dasselbe Ergebnis, und bei der Angabe von Systemeigenschaften besteht keine Chance, einen Tippfehler einzuführen.

Es besteht eine große Chance, dass Sie bereits eine Apache CommonsIO-Bibliothek in Ihrem Projekt haben. Führen Sie es nicht ein, wenn Sie beabsichtigen, es nur zum Abrufen des Benutzerverzeichnisses zu verwenden.

0
mladzo