Come ottenere l'attuale directory di lavoro in Java?


1029

Voglio accedere alla mia directory di lavoro corrente utilizzando Java.

Il mio codice:

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

Produzione:

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

Il mio output non è corretto perché l'unità C non è la mia directory corrente.

Come ottenere la directory corrente?


2
puoi incollare qui ciò che vedi quando esegui il cdcomando sul prompt dei comandi quando lo esegui?
Nishant,

3
Cosa stai cercando di realizzare accedendo alla directory di lavoro? Potrebbe essere fatto utilizzando invece il percorso di classe? Ad esempio, se è necessario leggere un file di testo sul file system, è possibile trovarlo facilmente quando si trova sul percorso della classe.
Earldouglas,

1
Come? Potresti elaborare per favore?
Grafica C

1
Per alcune informazioni su accesso a un file nel percorso di classe, vedere stackoverflow.com/questions/1464291/...
downeyt

7
Ai fini del debug, la directory di lavoro potrebbe essere utile per sapere se il programma non sembra essere in grado di accedere ai file esistenti.
nsandersen,

Risposte:


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

Questo stamperà un percorso assoluto completo da dove è stata inizializzata l'applicazione.


Dalla documentazione :

java.ioil pacchetto risolve i percorsi relativi usando la directory utente corrente. La directory corrente è rappresentata come proprietà di sistema, ovvero user.dired è la directory da cui è stata richiamata la JVM.


25
@ubuntudroid: ecco perché ho menzionato in modo specifico che stamperà il percorso da cui l'applicazione era stata inizializzata. Immagino che lo starter thread esegua direttamente il jar / programma dopo aver avviato il prompt dei comandi (che si trova sostanzialmente in C: \ WINDOWS \ system32). Spero tu capisca il mio punto. Supponendo di aver effettuato il downgrade, apprezzare che almeno ci tenesse a lasciare una risposta. :)
Anuj Patel,

1
user.dir otterrà il percorso della cartella in cui è stato avviato il processo. Per ottenere il percorso effettivo alla cartella principale dell'applicazione, vedere la mia risposta di seguito.
Peter De Winter,

1
Voglio dire "tutto il codice che fa affidamento su di esso per trovare la directory corrente non riesce.". Non tutto il codice in generale. (Ho dovuto rallentare per modificare il commento originale)
SubOptimal

13
@SubOptimal se l'utente ha impostato -Duser.dir, è propenso a volerlo eseguire nella directory di lavoro personalizzata.
Barwnikk,

5
@indyaah infatti questa risposta è sbagliata, c'è una sottile differenza tra una directory di lavoro dell'utente e una directory di lavoro corrente di un processo di sistema (cwd); il più delle volte "user.dir" punta alla cwd di un processo (java); ma "user.dir" ha una semantica diversa e non deve essere usato per ottenere il CWD di un processo Java; btw: ci sono più proprietà disponibili per il processo java docs.oracle.com/javase/tutorial/essential/environment/… solo per riferimento
comeGetSome

382

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

Usando java.nio.file.Pathe java.nio.file.Paths, puoi fare quanto segue per mostrare ciò che Java pensa sia il tuo percorso attuale. Questo per 7 e oltre, e utilizza NIO.

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

Ciò produce Current relative path is: /Users/george/NetBeansProjects/Tutorialsche nel mio caso è da dove ho tenuto la classe. Costruire percorsi in modo relativo, non usando un separatore principale per indicare che stai costruendo un percorso assoluto, utilizzerà questo percorso relativo come punto di partenza.


2
Il primo non è stato verificato, ma il secondo otterrà effettivamente la cartella principale. Non l'attuale directory di lavoro in cui è in esecuzione l'applicazione.
Peter De Winter,

12
Non confondere la home directory dell'utente ("user.home", / Users / george nel tuo caso) e la directory di lavoro corrente ("user.dir", che sarà la directory da cui hai avviato la JVM per la tua applicazione , quindi potrebbe essere qualcosa come eg / Users / george / workspace / FooBarProject).
David,

1
Preferisco così. Quando ho bisogno del genitore della directory di lavoro, questo non funziona: Paths.get("").getParent()null. Invece questo funziona: Paths.get("").toAbsolutePath().getParent().
Ole VV,

235

Quanto segue funziona su Java 7 e versioni successive (vedere qui per la documentazione).

import java.nio.file.Paths;

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

11
In che modo è meglio del più portatile import java.io.File; File(".").getAbsolutePath()?
Evgeni Sergeev,

8
Quando dici portatile, vuoi dire che funziona in Java 6 e precedenti? Paths.get()può essere considerato migliore in quanto consente l'accesso diretto all'interfaccia più potente Path.
Ole VV,

8
Qual è il potenziale vantaggio dell'utilizzo .normalize()in questo contesto?
Ole VV,

7
@ OleV.V. Da Javadoc: ( metodo di normalizzazione )Returns a path that is this path with redundant name elements eliminated.
Stephan,

In questo caso sarebbe già normalizzato.
JM Becker

73

Questo ti darà il percorso della tua attuale directory di lavoro:

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

E questo ti darà il percorso di un file chiamato "Foo.txt" nella directory di lavoro:

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

Modifica: per ottenere un percorso assoluto della directory corrente:

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

* Aggiorna * Per ottenere la directory di lavoro corrente:

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

11
questo restituisce semplicemente '.' per me.
john ktejik,

3
Sì, in molti sistemi sarà il riferimento alla directory di lavoro. Per ottenere il percorso assoluto è possibile aggiungere un'altra chiamata di metodoPath path = FileSystems.getDefault().getPath(".").toAbsolutePath();
contrassegnare il

2
Non è necessario il foo.txt, basta inserire una stringa vuota per ottenere la directory
john ktejik

1
Su Windows (10) questo mi dà solo un Pathoggetto che punta a un file chiamato .all'interno della directory di lavoro corrente. Usando una stringa vuota, piuttosto che ha "."funzionato per me.
Kröw,

36

Questa è la soluzione per me

File currentDir = new File("");

1
Ciò ha effetti collaterali quando si utilizza un oggetto File come genitore di un altro file: il nuovo file (nuovo file (""), "sottodir") non funzionerà come previsto
MRalwasser,

13
Per risolvere questo problema, utilizzare new File("").getAbsoluteFile()invece.
MRalwasser,

4
Per quello che vale, ho avuto più fortuna con File (".").
Keshlam,

Come definire un percorso relativo in Java Questa pagina mi ha aiutato. Inoltre ho assunto che dovrei usare /quando si crea un percorso relativo. Ho sbagliato, non iniziare /. ../funziona anche per salire nell'albero delle directory.
Irrationalkilla,

@keshlam Mi ha dato un file nella directory corrente chiamata ..
Kröw,

32

Ho trovato questa soluzione nei commenti che è migliore di altri e più portatile:

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

O anche

String cwd = Paths.get("").toAbsolutePath();

Questa è esattamente la stessa risposta di comeGetSome ed è in realtà il modo Java <7
GoGoris

30

Cosa ti fa pensare che c: \ windows \ system32 non sia la tua directory attuale? La user.dirproprietà deve essere esplicitamente "Directory di lavoro corrente dell'utente".

Per dirla in altro modo, a meno che non si avvii Java dalla riga di comando, c: \ windows \ system32 probabilmente è il CWD. Cioè, se si fa doppio clic per avviare il programma, è improbabile che il CWD sia la directory da cui si fa doppio clic.

Modifica : sembra che ciò sia vero solo per vecchie versioni di Windows e / o Java.


2
Questo non sembra essere vero, almeno non sul mio computer Windows 7 che utilizza Java 7. user.dirè costantemente la cartella in cui ho fatto doppio clic sul file jar.
Jolta,

26

Usa CodeSource#getLocation().

Funziona bene anche nei file JAR. È possibile ottenere CodeSourceda ProtectionDomain#getCodeSource()e il ProtectionDomaina sua volta può essere ottenuto da 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());
    }
}

2
Ciò restituisce il percorso del file JAR. Non quello che è stato chiesto.
Marchese di Lorne,

22
this.getClass().getClassLoader().getResource("").getPath()

12
Genera un NPE all'avvio dell'applicazione da un file JAR facendo doppio clic su di esso.
Matthew Wise,

2
Ciò restituisce ""se l'applicazione è in esecuzione da un file JAR o da un elemento CLASSPATH. Non quello che è stato chiesto.
Marchese di Lorne,

@ Zizouz212 getClass()è un metodo oggetto, quindi in un contesto statico la semplice rimozione di thisnon funziona. Dovresti fare esplicito riferimento alla classe che stai frequentando facendo MyClass.class.getClassLoader()......
Kröw,

Tuttavia non restituirà la directory di lavoro ...
Angel O'Sphere,

18

generalmente, come oggetto File:

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

potresti voler avere una stringa qualificata come "D: / a / b / c" che fa:

getCwd().getAbsolutePath()

1
Funziona bene nei test Android poiché Android non include java.nio.file.Files.
iamreptar,

Non sembra funzionare per me in un contesto statico (il nuovo file ("") genera NullPointerException) ..?
nsandersen,

2
@nsandersen probabilmente hai usato un oggetto File errato: System.out.println (new java.io.File (""). getAbsolutePath ());
comeGetSome


5

Su Linux quando si esegue un file jar dal terminale , entrambi restituiranno lo stesso String: "/ home / CurrentUser" , indipendentemente da dove si trovi il file jar. Dipende solo dalla directory corrente che stai usando con il tuo terminale, quando avvii il file jar.

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

System.getProperty("user.dir");

Se il tuo Classcon mainsarebbe chiamato MainClass, quindi prova:

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

Ciò restituirà un percorso assolutoString con il file jar .


3
Non è quello che è stato chiesto.
Marchese di Lorne,

5

L'uso di user.dir di Windows restituisce la directory come previsto, ma NON quando si avvia l'applicazione con diritti elevati (esegui come admin), in tal caso si ottiene C: \ WINDOWS \ system32


3

Spero che tu voglia accedere alla directory corrente incluso il pacchetto, ad esempio se il tuo programma Java è attivo c:\myApp\com\foo\src\service\MyTest.javae vuoi stampare fino a c:\myApp\com\foo\src\servicequel momento puoi provare il seguente codice:

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: questo codice è testato solo in Windows con Oracle JRE.


6
Sarebbe disservizio non sottovalutare questa risposta. Ti preghiamo di pensare più attentamente prima di pubblicare. Il tuo codice è rotto, a meno che non siano tutti veri: 1. JRE è di Oracle, altrimenti non ci sarà alcuna proprietà di sistema "sun.java.command" → NPE; 2. il sistema operativo è Windows (utilizzare File.separatorinvece o un Filecostruttore multi-argomento ); 3. il classpath è specificato sulla riga di comando e la 'directory corrente incluso il pacchetto' (??) è: a. specificato prima, b. specificato assolutamente, c. corrisponde esattamente al CWD (anche con insensibilità al maiuscolo / minuscolo di Windows) e d. è un discendente del CWD
Michael Scheper,

Che affronta i punti 1 e 2. Ma a meno che non mi manchi qualcosa, stai ancora facendo affidamento sul percorso di classe specificato nella riga di comando (cioè non in una variabile di ambiente) e per la "directory corrente incluso il pacchetto" (I ammetto che non capisco davvero cosa intendi per questo) essere un discendente del primo elemento nel percorso di classe. E il problema di corrispondenza del caso rimane. Mi dispiace se il mio commento non è stato utile; Ho sacrificato la chiarezza per mantenere il limite del carattere del commento.
Michael Scheper,

@Inversus, funziona solo "perfettamente" in alcuni ambienti; ti è capitato di essere abbastanza fortunato da provarlo in uno di questi. Scrivere software che fallisce negli ambienti di runtime legittimi non è una buona pratica, anche quando il tuo set di ambienti di test non è sufficientemente ampio da includerli.
Charles Duffy,

@CharlesDuffy Hai ragione, questa non è una buona pratica. Fortunatamente, questa soluzione "risolve il mio problema specifico" non ha causato il suo "fallimento" in ambienti di runtime legittimi ". In effetti, mi ha aiutato a risolvere un simile errore e a scrivere un codice più solido, oltre a risolvere il problema molto specifico che avevo (che era solo in qualche modo correlato a questa domanda / risposta). Immagino di essere stato solo fortunato a trovarlo.
Inversus,

3

Menzione che è registrato solo in Windowsma penso che funzioni perfettamente su altri sistemi operativi [ Linux,MacOs,Solaris] :).


Ho avuto 2 .jar file nella stessa directory. Volevo da un .jarfile avviare l'altro .jarfile che si trova nella stessa directory.

Il problema è che quando lo si avvia dalla cmddirectory corrente è system32.


Avvertenze!

  • Quanto segue sembra funzionare abbastanza bene in tutti i test che ho fatto anche con il nome della cartella ;][[;'57f2g34g87-8+9-09!2#@!$%^^&()o ()%&$%^@# funziona bene.
  • Sto usando il ProcessBuildercon il seguito come segue:

🍂 ..

//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;
    }

Ciò restituisce il percorso del file JAR. Non quello che è stato chiesto.
Marchese di Lorne,

@EJP La posizione del file .jar non è la directory di lavoro corrente del programma java?
GOXR3PLUS,

2

La directory di lavoro corrente è definita in modo diverso nelle diverse implementazioni Java. Per alcune versioni precedenti a Java 7 non esisteva un modo coerente per ottenere la directory di lavoro. È possibile aggirare il problema avviando il file Java con -De definendo una variabile per contenere le informazioni

Qualcosa di simile a

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

Non è del tutto giusto, ma hai l'idea. Allora System.getProperty("com.mycompany.workingDir")...


6
Non pertinente alla domanda.
Peter De Winter,

1
Ha un significato per Java: è la posizione sul disco in cui sono relativi i file che si aprono con relativi percorsi.
Rob I,

2
Sì, ha un significato. Le mie parole sono state scelte in qualche modo male. Ma ti manca il punto: prima di Java 7 non c'era modo di conoscere la directory di lavoro corrente e diverse implementazioni le impostavano ... in modo diverso ...
MJB

1

supponi che stai provando a eseguire il tuo progetto all'interno di eclipse, o netbean o stand-alone dalla riga di comando. Ho scritto un metodo per risolverlo

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

Per usare, ovunque tu voglia ottenere il percorso base per leggere il file, puoi passare la tua classe di ancoraggio al metodo sopra, il risultato potrebbe essere quello che ti serve: D

Migliore,


2
Ciò restituisce il percorso del file JAR. Non quello che è stato chiesto.
Marchese di Lorne,

@ user207421 Sì, so che questa risposta non è la vera risposta alla domanda, ma la maggior parte delle volte tutti vogliono ottenere la "directory in cui si trovano i barattoli" invece di "directory di lavoro della riga di comando".
bachden

0

Nessuna delle risposte pubblicate qui ha funzionato per me. Ecco cosa ha funzionato:

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

Modifica: la versione finale nel mio codice:

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

Ciò restituisce il percorso del file JAR. Non quello che è stato chiesto.
Marchese di Lorne,

0

Questo è il mio proiettile d'argento ogni volta che arriva il momento di confusione. (Chiamalo come prima cosa principale). Forse, ad esempio, JVM è considerato diverso da IDE. Questa funzione statica ricerca il PID del processo corrente e apre VisualVM su quel pid. La confusione si ferma proprio lì perché vuoi tutto e lo ottieni ...

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


-7

questo è il nome della directory corrente

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

questo è il percorso della directory corrente

String path=folder.getPath();

1
L'OP voleva l'attuale directory di lavoro da cui era stata eseguita l'applicazione.
Leif Gruenwoldt,

Questa è la tua home directory, non l'attuale directory di lavoro di nessuno, tranne forse la tua. Non quello che è stato chiesto.
Marchese di Lorne,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.