Pergunta

A dificuldade é que ele deve ser multiplataforma. Windows 2000, XP, Vista, OSX, Linux, outras variantes do Unix. Eu estou procurando um trecho de código que pode fazer isso para todas as plataformas, e uma maneira de detectar a plataforma.

Agora, você deve estar ciente de bug 4787931 que user.home faz não funcionar corretamente, então por favor não me fornecer respostas de livros didáticos, posso encontrá-los eu mesmo nos manuais.

Foi útil?

Solução

O bug você referência (bug 4787391) foi corrigido no Java 8. Mesmo se você estiver usando uma versão mais antiga do Java, a abordagem System.getProperty("user.home") é provavelmente ainda o melhor. A abordagem user.home parece funcionar em um número muito grande de casos. Uma solução à prova de balas 100% no Windows é difícil, porque o Windows tem um conceito deslocando do que os meios de diretório casa.
Se user.home não é bom o suficiente para você eu sugiro escolher uma definição de home directory para Windows e usá-lo, ficando a variável de ambiente adequado, com System.getenv(String).

Outras dicas

Na verdade, com o Java 8 da maneira correta é usar:

System.getProperty("user.home");

O bug JDK-6519127 foi corrigido eo "Incompatibilidades entre JDK 8 e JDK 7" seção dos estados:

Área: Núcleo libs / java.lang

Sinopse

Os passos utilizados para determinar o diretório home do usuário no Windows mudaram para seguir a abordagem da Microsoft recomendado. esta mudança pode ser observável em edições mais antigas do Windows, ou quando do registro definições ou variáveis ??de ambiente são definidas para outros diretórios. Natureza de incompatibilidade

behavioral RFE

6519127

Apesar da questão ser velho Deixo isso para referência futura.

System.getProperty("user.home");

Veja a JavaDoc .

O conceito de um diretório home parece ser um pouco vago quando se trata do Windows. Se o variáveis ??de ambiente (HOMEDRIVE / HOMEPATH / USERPROFILE) não é suficiente se, você pode ter que recorrer ao uso de funções nativas através de JNI ou JNA . SHGetFolderPath permite recuperar pastas especiais, como < em> Meus documentos (CSIDL_PERSONAL) ou local Settings \ Application Data (CSIDL_LOCAL_APPDATA).

código JNA Amostra:

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

    }

}

Outros têm respondido à pergunta antes de mim, mas um programa útil para imprimir todas as propriedades disponíveis é:

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

Como eu estava procurando versão Scala, tudo o que eu poderia encontrar era código JNA de McDowell acima. Eu incluo a minha porta Scala aqui, como atualmente não é em qualquer lugar mais apropriado.

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

Tal como acontece com a versão Java, você vai precisar adicionar Java Native Acesso , incluindo os arquivos jar, às suas bibliotecas de referência.

É bom ver que JNA agora torna isso muito mais fácil do que quando o código original foi publicado.

Gostaria de usar o algoritmo detalhado no relatório de bug usando System.getenv (String), e fallback para o uso da propriedade user.dir se nenhuma das variáveis ??de ambiente indicou um diretório existente válido. Isso deve funcionar cross-platform.

Eu acho que, no Windows, o que você está realmente depois é nocionais "documentos" do usuário diretório.

Se você quer algo que funciona bem em Windows, existe um pacote chamado WinFoldersJava que envolve o nativo ligar para obter os diretórios 'especiais' no Windows. Nós usá-lo com frequência e ele funciona bem.

Alternativa seria usar Apache CommonsIO FileUtils.getUserDirectory() vez de System.getProperty("user.home"). Ele vai te dar o mesmo resultado e não há nenhuma chance de apresentar um erro de digitação ao especificar propriedade do sistema.

Há uma grande chance que você já tem biblioteca Apache CommonsIO em seu projeto. Não apresentá-lo, se você pretende usá-lo apenas para obter diretório home do usuário.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top