Como obter o diretório de trabalho atual em Java?

1029

Quero acessar meu diretório de trabalho atual usando java.

Meu código:

 String current = new java.io.File( "." ).getCanonicalPath();
        System.out.println("Current dir:"+current);
 String currentDir = System.getProperty("user.dir");
        System.out.println("Current dir using System:" +currentDir);

Resultado:

Current dir: C:\WINDOWS\system32
Current dir using System: C:\WINDOWS\system32

Minha saída não está correta porque a unidade C não é meu diretório atual.

Como obter o diretório atual?

Qazi
fonte
2
você pode colar aqui o que vê quando executa o cdcomando no prompt de comando ao executar isso?
Nishant 02/02
3
O que você está tentando realizar acessando o diretório de trabalho? Isso poderia ser feito usando o caminho da classe? Por exemplo, se você precisar ler um arquivo de texto no sistema de arquivos, poderá encontrá-lo facilmente quando estiver no caminho da classe.
earldouglas
1
como? Você poderia elaborar por favor?
Gráficos C
1
Para obter algumas informações sobre como acessar um arquivo no caminho da classe, consulte stackoverflow.com/questions/1464291/…
downeyt
7
Para fins de depuração, o diretório de trabalho pode ser útil para saber se o programa parece não conseguir acessar os arquivos existentes.
Nsandersen

Respostas:

1152
public class JavaApplication {
  public static void main(String[] args) {
       System.out.println("Working Directory = " + System.getProperty("user.dir"));
  }
}

Isso imprimirá um caminho absoluto completo de onde seu aplicativo foi inicializado.


A partir da documentação :

java.iopacote resolve nomes de caminho relativos usando o diretório de usuário atual. O diretório atual é representado como propriedade do sistema, ou seja, user.dire é o diretório de onde a JVM foi chamada.

Anuj Patel
fonte
25
@ubuntudroid: é por isso que mencionei especificamente que ele imprimirá o caminho de onde o aplicativo foi inicializado. Meu palpite é que o iniciador de threads execute diretamente o jar / programa após iniciar o prompt do commnad (que é basicamente em C: \ WINDOWS \ system32). Espero que você entenda meu argumento. Supondo que você tenha votado mal, saiba que pelo menos você se importou em deixar uma resposta. :)
Anuj Patel
1
user.dir obterá o caminho para a pasta em que o processo foi iniciado. Para obter o caminho real para a pasta principal do aplicativo, veja minha resposta abaixo.
Peter De Winter
1
Quero dizer "todo o código que depende dele para encontrar o diretório atual falha". Nem todo o código em geral. (Eu era lento para editar o comentário original)
Suboptimal
13
@SubOptimal se o usuário configurou -Duser.dir, é possível que ele queira executar isso no diretório de trabalho personalizado.
barwnikk
5
@indyaah De fato, esta resposta está errada, há uma diferença sutil entre um diretório de trabalho do usuário e um diretório de trabalho atual de um processo do sistema (cwd); na maioria das vezes o "user.dir" aponta para o código de um processo (java); mas "user.dir" possui semântica diferente e não deve ser usado para obter o cwd de um processo java; btw: há mais imóveis à java processo docs.oracle.com/javase/tutorial/essential/environment/... apenas para referência
comeGetSome
382

Consulte: http://docs.oracle.com/javase/tutorial/essential/io/pathOps.html

Usando java.nio.file.Pathe java.nio.file.Paths, você pode fazer o seguinte para mostrar o que Java acha que é o seu caminho atual. Isso para 7 em diante e usa o NIO.

Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + s);

Isso Current relative path is: /Users/george/NetBeansProjects/Tutorialsmostra que, no meu caso, é de onde eu executei a classe. Construir caminhos de maneira relativa, ao não usar um separador à esquerda para indicar que você está construindo um caminho absoluto, usará esse caminho relativo como ponto de partida.

geoO
fonte
2
O primeiro não foi verificado, mas o segundo realmente receberá sua pasta pessoal. Não é o diretório de trabalho atual no qual o aplicativo está sendo executado.
Peter De Winter
12
Não confunda o diretório inicial do usuário ("user.home", / Users / george no seu caso) e o diretório ativo atual ("user.dir", que será o diretório a partir do qual você iniciou a JVM para seu aplicativo , pode ser algo como, por exemplo, / Users / george / workspace / FooBarProject).
David
1
Eu prefiro assim. Quando eu preciso do pai do diretório de trabalho, isso não funciona Paths.get("").getParent():, ele fornece null. Em vez isso funciona: Paths.get("").toAbsolutePath().getParent().
Ole VV
235

O seguinte funciona no Java 7 e superior (veja aqui para documentação).

import java.nio.file.Paths;

Paths.get(".").toAbsolutePath().normalize().toString();
Dmitry Bespalov
fonte
11
Como isso é melhor do que o mais portátil import java.io.File; File(".").getAbsolutePath()?
Evgeni Sergeev
8
Quando você diz portátil, quer dizer que funciona em Java 6 e versões anteriores? Paths.get()pode ser considerado melhor, pois fornece acesso direto à Pathinterface mais poderosa .
Ole VV
8
Qual é a vantagem potencial de usar .normalize()neste contexto?
Ole VV
7
@ OleV.V. De Javadoc: ( método normalizar )Returns a path that is this path with redundant name elements eliminated.
Stephan
Já seria normalizado neste caso.
JM Becker
73

Isso fornecerá o caminho do seu diretório de trabalho atual:

Path path = FileSystems.getDefault().getPath(".");

E isso lhe dará o caminho para um arquivo chamado "Foo.txt" no diretório de trabalho:

Path path = FileSystems.getDefault().getPath("Foo.txt");

Edit: Para obter um caminho absoluto do diretório atual:

Path path = FileSystems.getDefault().getPath(".").toAbsolutePath();

* Atualização * Para obter o diretório de trabalho atual:

Path path = FileSystems.getDefault().getPath("").toAbsolutePath();
Marca
fonte
11
isso apenas retorna '.' para mim.
John ktejik
3
Sim, em muitos sistemas que serão a referência ao diretório de trabalho. Para obter o caminho absoluto você pode adicionar mais uma chamada de métodoPath path = FileSystems.getDefault().getPath(".").toAbsolutePath();
Mark
2
Você não precisa do foo.txt, basta colocar em uma cadeia vazia para obter o diretório
john ktejik
1
No Windows (10), isso apenas me fornece um Pathobjeto apontando para um arquivo chamado .dentro do diretório de trabalho atual. Usando uma string vazia, em vez de "."funcionar para mim.
Kröw 18/04/19
36

Esta é a solução para mim

File currentDir = new File("");
user2430452
fonte
1
Isto tem efeitos colaterais quando você usa tal objeto um arquivo como um pai de outro arquivo: new File (new File ( ""), "subdir") não funcionará como esperado
MRalwasser
13
Para corrigir isso, use em new File("").getAbsoluteFile()vez disso.
MRalwasser
4
Pelo que vale, tive mais sorte com o File (".").
precisa saber é o seguinte
Como definir um caminho relativo em Java Esta página me ajudou. Também assumi que deveria usar /ao criar um caminho relativo. Eu estava errado, não comece /. ../também funciona para subir na árvore de diretórios.
precisa
@keshlam Isso me deu um arquivo no diretório atual chamado ..
Kröw 2/06/19
32

Encontrei esta solução nos comentários, melhor do que outros e mais portátil:

String cwd = new File("").getAbsolutePath();

Ou até

String cwd = Paths.get("").toAbsolutePath();
freedev
fonte
Isso é exatamente o mesmo que a resposta de comeGetSome e é realmente o caminho Java <7
GoGoris 03/01
30

O que faz você pensar que c: \ windows \ system32 não é seu diretório atual? A user.dirpropriedade deve ser explicitamente "Diretório de trabalho atual do usuário".

Em outras palavras, a menos que você inicie o Java na linha de comando, c: \ windows \ system32 provavelmente é o seu CWD. Ou seja, se você clicar duas vezes para iniciar o programa, é improvável que o CWD seja o diretório em que você está clicando duas vezes.

Editar : parece que isso só é verdade para janelas antigas e / ou versões Java.

Paul Wagland
fonte
2
Isso não parece ser verdade, pelo menos não na minha máquina Windows 7 usando Java 7. user.diré sempre a pasta em que cliquei duas vezes no arquivo jar.
Jolta
26

Use CodeSource#getLocation().

Isso funciona bem em arquivos JAR também. Você pode obter CodeSourcepor ProtectionDomain#getCodeSource()e, por ProtectionDomainsua vez, pode ser obtido por Class#getProtectionDomain().

public class Test {
    public static void main(String... args) throws Exception {
        URL location = Test.class.getProtectionDomain().getCodeSource().getLocation();
        System.out.println(location.getFile());
    }
}
Bigoloo
fonte
2
Isso retorna o local do arquivo JAR. Não foi o que foi pedido.
Marquês de Lorne #
22
this.getClass().getClassLoader().getResource("").getPath()
Peter De Winter
fonte
12
Lança um NPE quando inicio meu aplicativo a partir de um arquivo JAR clicando duas vezes nele.
Matthew Wise
2
Isso retorna ""se o aplicativo estiver sendo executado a partir de um arquivo JAR ou um elemento CLASSPATH. Não foi o que foi pedido.
Marquês de Lorne #
@ Zizouz212 getClass()é um método de objeto, portanto, em um contexto estático, apenas remover o thisnão funciona. Você teria que se referir explicitamente à classe em que está participando MyClass.class.getClassLoader()......
Kröw 2/06/19
No entanto, ele não retornará o diretório de trabalho ...
Angel O'Sphere 14/10
18

geralmente, como um objeto File:

File getCwd() {
  return new File("").getAbsoluteFile();
}

você pode querer ter uma sequência completa qualificada como "D: / a / b / c", fazendo:

getCwd().getAbsolutePath()
comeGetSome
fonte
1
Isso funciona bem nos testes do Android, pois o Android não inclui java.nio.file.Files.
Iamreptar # 29/15
Parece não funcionar para mim em um contexto estático (o novo arquivo ("") lança NullPointerException)) ..?
Nsandersen
2
@nsandersen você provavelmente usou um objeto File errado: System.out.println (new java.io.File (""). getAbsolutePath ());
comeGetSome
5

No Linux, quando você executa um arquivo jar no terminal , ambos retornam o mesmo String: "/ home / CurrentUser" , não importa onde esteja o arquivo jar. Depende apenas do diretório atual que você está usando com o seu terminal, quando inicia o arquivo jar.

Paths.get("").toAbsolutePath().toString();

System.getProperty("user.dir");

Se o seu Classcom mainseria chamado MainClass, então tente:

MainClass.class.getProtectionDomain().getCodeSource().getLocation().getFile();

Isso retornará um Stringcom caminho absoluto do arquivo jar .

Jan Povolný
fonte
3
O que não foi solicitado.
Marquês de Lorne #
5

O uso do Windows user.dir retorna o diretório conforme o esperado, mas NÃO quando você inicia o aplicativo com direitos elevados (executado como admin); nesse caso, você obtém C: \ WINDOWS \ system32

SijeDeHaan
fonte
3

Espero que você queira acessar o diretório atual, incluindo o pacote, ou seja, se o seu programa Java estiver presente c:\myApp\com\foo\src\service\MyTest.javae você desejar imprimir até c:\myApp\com\foo\src\serviceentão, tente o seguinte código:

String myCurrentDir = System.getProperty("user.dir")
            + File.separator
            + System.getProperty("sun.java.command")
                    .substring(0, System.getProperty("sun.java.command").lastIndexOf("."))
                    .replace(".", File.separator);
    System.out.println(myCurrentDir);

Nota: Este código é testado apenas no Windows com Oracle JRE.

JSS
fonte
6
Seria um desserviço não rebaixar esta resposta. Por favor, pense com mais cuidado antes de postar. Seu código está quebrado, a menos que tudo isso seja verdadeiro: 1. o JRE é do Oracle, caso contrário, não haverá nenhuma propriedade do sistema "sun.java.command" → NPE; 2. o sistema operacional é Windows (use em File.separatorvez disso, ou um Fileconstrutor de vários argumentos ); 3. o caminho da classe é especificado na linha de comando e o 'diretório atual incluindo o pacote' (??) é: a. especificado primeiro, b. especificado absolutamente, c. corresponde exatamente ao CWD (mesmo com a distinção entre maiúsculas e minúsculas do Windows) e d. é um descendente do CWD
Michael Scheper
Isso aborda os pontos 1 e 2. Mas, a menos que esteja faltando alguma coisa, você ainda está confiando no caminho de classe sendo especificado na linha de comando (ou seja, não em uma variável de ambiente) e no 'diretório atual, incluindo o pacote' (I admita que realmente não entendo o que você quer dizer com isso) ser um descendente especificamente do primeiro elemento no caminho de classe. E o problema de correspondência de casos permanece. Sinto muito se meu comentário não foi útil; Eu sacrifiquei a clareza para manter o limite de caracteres do comentário.
Michael Scheper
@ Inversus, apenas "funciona perfeitamente" em alguns ambientes; por acaso você teve a sorte de testá-lo em alguns. Escrever software que falha em ambientes de tempo de execução legítimos não é uma boa prática, mesmo quando seu conjunto de ambientes de teste não é amplo o suficiente para incluí-los.
Charles Duffy
@CharlesDuffy Você está certo, isso não é uma boa prática. Felizmente, essa solução "solucionando meu problema específico" não fez com que "falhasse em ambientes de tempo de execução legítimos". De fato, isso me ajudou a resolver essa falha e a escrever um código mais robusto, além de resolver o problema muito específico que eu tinha (que estava apenas um pouco relacionado a essa pergunta / resposta). Acho que tive a sorte de encontrá-lo.
Inversus
3

Mencione que ele está marcado apenas Windowsmas acho que funciona perfeitamente em outros sistemas operacionais [ Linux,MacOs,Solaris] :).


Eu tinha 2 .jar arquivos no mesmo diretório. Eu queria que um .jararquivo iniciasse o outro .jararquivo que está no mesmo diretório.

O problema é que, quando você o inicia cmdno diretório atual, é system32.


Advertências!

  • O abaixo parece funcionar muito bem em todos os testes que fiz, mesmo com o nome da pasta ;][[;'57f2g34g87-8+9-09!2#@!$%^^&()ou ()%&$%^@# funciona bem.
  • Estou usando o ProcessBuildercom o seguinte, como a seguir:

🍂 ..

//The class from which i called this was the class `Main`
String path = getBasePathForClass(Main.class);
String applicationPath=  new File(path + "application.jar").getAbsolutePath();


System.out.println("Directory Path is : "+applicationPath);

//Your know try catch here
//Mention that sometimes it doesn't work for example with folder `;][[;'57f2g34g87-8+9-09!2#@!$%^^&()` 
ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath);
builder.redirectErrorStream(true);
Process process = builder.start();

//...code

🍂 getBasePathForClass(Class<?> classs):

    /**
     * Returns the absolute path of the current directory in which the given
     * class
     * file is.
     * 
     * @param classs
     * @return The absolute path of the current directory in which the class
     *         file is.
     * @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user]
     */
    public static final String getBasePathForClass(Class<?> classs) {

        // Local variables
        File file;
        String basePath = "";
        boolean failed = false;

        // Let's give a first try
        try {
            file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());

            if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
                basePath = file.getParent();
            } else {
                basePath = file.getPath();
            }
        } catch (URISyntaxException ex) {
            failed = true;
            Logger.getLogger(classs.getName()).log(Level.WARNING,
                    "Cannot firgue out base path for class with way (1): ", ex);
        }

        // The above failed?
        if (failed) {
            try {
                file = new File(classs.getClassLoader().getResource("").toURI().getPath());
                basePath = file.getAbsolutePath();

                // the below is for testing purposes...
                // starts with File.separator?
                // String l = local.replaceFirst("[" + File.separator +
                // "/\\\\]", "")
            } catch (URISyntaxException ex) {
                Logger.getLogger(classs.getName()).log(Level.WARNING,
                        "Cannot firgue out base path for class with way (2): ", ex);
            }
        }

        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbeans
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    }
GOXR3PLUS
fonte
Isso retorna o local do arquivo JAR. Não foi o que foi pedido.
Marquês de Lorne #
@EJP A localização do arquivo .jar não é o diretório de trabalho atual do programa java?
GOXR3PLUS
2

O diretório de trabalho atual é definido de maneira diferente em diferentes implementações Java. Para determinadas versões anteriores ao Java 7, não havia uma maneira consistente de obter o diretório de trabalho. Você pode contornar isso iniciando o arquivo Java -De definindo uma variável para conter as informações

Algo como

java -D com.mycompany.workingDir="%0"

Isso não está certo, mas você entendeu. Então System.getProperty("com.mycompany.workingDir")...

MJB
fonte
6
Não é relevante para a pergunta.
Peter De Winter
1
Ele tem um significado para Java - é o local no disco em que os arquivos que você abre com nomes de caminho relativos são relativos.
Rob I
2
Sim, tem um significado. Minhas palavras foram um pouco mal escolhidas. Mas você perder o ponto - antes de Java 7 não havia nenhuma maneira de saber o diretório de trabalho atual, e diferentes implementações defini-los ... diferente ...
MJB
1

suponha que você esteja tentando executar seu projeto dentro do eclipse ou netbean ou independente da linha de comando. Eu escrevi um método para corrigi-lo

public static final String getBasePathForClass(Class<?> clazz) {
    File file;
    try {
        String basePath = null;
        file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
            basePath = file.getParent();
        } else {
            basePath = file.getPath();
        }
        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbean
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    } catch (URISyntaxException e) {
        throw new RuntimeException("Cannot firgue out base path for class: " + clazz.getName());
    }
}

Para usar, em qualquer lugar que você deseja obter o caminho base para ler o arquivo, você pode passar sua classe âncora para o método acima, o resultado pode ser o que você precisa: D

melhor,

Bachden
fonte
2
Isso retorna o local do arquivo JAR. Não foi o que foi pedido.
Marquês de Lorne #
@ user207421 sim, eu sei que esta resposta não é a resposta verdadeira para a pergunta, mas na maioria das vezes, todos desejam obter o "diretório onde os frascos localizados" em vez de "diretório de trabalho da linha de comando".
bachden
0

Nenhuma das respostas postadas aqui funcionou para mim. Aqui está o que funcionou:

java.nio.file.Paths.get(
  getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
);

Edit: A versão final no meu código:

URL myURL = getClass().getProtectionDomain().getCodeSource().getLocation();
java.net.URI myURI = null;
try {
    myURI = myURL.toURI();
} catch (URISyntaxException e1) 
{}
return java.nio.file.Paths.get(myURI).toFile().toString()
VenerableAgents
fonte
Isso retorna o local do arquivo JAR. Não foi o que foi pedido.
Marquês de Lorne #
0

Esta é a minha bala de prata sempre que surge o momento de confusão. (Chame como a primeira coisa em geral). Talvez, por exemplo, a JVM tenha sido desviada para uma versão diferente pelo IDE. Essa função estática pesquisa o PID do processo atual e abre o VisualVM nesse pid. A confusão acaba aí porque você quer tudo e consegue ...

  public static void callJVisualVM() {
    System.out.println("USER:DIR!:" + System.getProperty("user.dir"));
    //next search current jdk/jre
    String jre_root = null;
    String start = "vir";
    try {
        java.lang.management.RuntimeMXBean runtime =
                java.lang.management.ManagementFactory.getRuntimeMXBean();
        String jvmName = runtime.getName();
        System.out.println("JVM Name = " + jvmName);
        long pid = Long.valueOf(jvmName.split("@")[0]);
        System.out.println("JVM PID  = " + pid);
        Runtime thisRun = Runtime.getRuntime();
        jre_root = System.getProperty("java.home");
        System.out.println("jre_root:" + jre_root);
        start = jre_root.concat("\\..\\bin\\jvisualvm.exe " + "--openpid " + pid);
        thisRun.exec(start);
    } catch (Exception e) {
        System.getProperties().list(System.out);
        e.printStackTrace();
    }
}
Kurskinen
fonte
-6

System.getProperty("java.class.path")

Marko Stojkovic
fonte
-7

este é o nome do diretório atual

String path="/home/prasad/Desktop/folderName";
File folder = new File(path);
String folderName=folder.getAbsoluteFile().getName();

este é o caminho do diretório atual

String path=folder.getPath();
Prasad De Silva
fonte
1
O OP queria o diretório de trabalho atual de onde o aplicativo foi executado.
Leif Gruenwoldt 5/11
Este é o seu diretório pessoal, não o diretório de trabalho atual de ninguém, exceto talvez o seu. Não foi o que foi pedido.
Marquês de Lorne