Jak uzyskać bieżący katalog roboczy w Javie?

1026

Chcę uzyskać dostęp do mojego bieżącego katalogu roboczego za pomocą java.

Mój kod:

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

Wynik:

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

Moje dane wyjściowe są nieprawidłowe, ponieważ dysk C nie jest moim bieżącym katalogiem.

Jak uzyskać bieżący katalog?

Qazi
źródło
2
czy możesz wkleić tutaj to, co widzisz po wykonaniu cdpolecenia w wierszu polecenia po wykonaniu?
Nishant
3
Co próbujesz osiągnąć, uzyskując dostęp do katalogu roboczego? Czy można to zrobić za pomocą ścieżki klasy? Na przykład, jeśli chcesz odczytać plik tekstowy w systemie plików, możesz go łatwo znaleźć, gdy znajduje się on na ścieżce klasy.
Earldouglas
1
w jaki sposób? Czy mógłbyś opracować proszę?
C grafika
1
Aby uzyskać informacje na temat uzyskiwania dostępu do pliku na ścieżce klasy, zobacz stackoverflow.com/questions/1464291/…
downeyt
7
Do celów debugowania przydatny może być katalog roboczy, jeśli wydaje się, że program nie może uzyskać dostępu do istniejących plików.
nsandersen

Odpowiedzi:

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

Spowoduje to wydrukowanie pełnej ścieżki bezwzględnej, z której zainicjowano aplikację.


Z dokumentacji :

java.iopakiet rozpoznaje względne ścieżki przy użyciu bieżącego katalogu użytkownika. Bieżący katalog jest reprezentowany jako właściwość systemowa, czyli user.dirkatalog, z którego została wywołana maszyna JVM.

Anuj Patel
źródło
25
@ubuntudroid: dlatego wspomniałem konkretnie, że wydrukuje ścieżkę od miejsca, w którym aplikacja została zainicjowana. Domyślam się, że starter wątków bezpośrednio uruchamia jar / program po uruchomieniu komendy commnad (która jest w zasadzie w C: \ WINDOWS \ system32). Mam nadzieję, że rozumiesz mój punkt widzenia. Zakładając, że przegłosowałeś, doceń, że przynajmniej chciałeś zostawić odpowiedź. :)
Anuj Patel
1
user.dir pobierze ścieżkę do folderu, w którym proces został uruchomiony. Aby uzyskać rzeczywistą ścieżkę do głównego folderu aplikacji, zobacz moją odpowiedź poniżej.
Peter De Winter,
1
Mam na myśli „cały kod polegający na nim w celu znalezienia bieżącego katalogu zawodzi”. Nie cały kod w ogóle. (Miałem spowolnić edycję oryginalnego komentarza)
SubOptimal
13
@SubOptimal, jeśli użytkownik ustawił -Duser.dir, możliwe, że chce uruchomić to w niestandardowym katalogu roboczym.
barwnikk 18.04.15
5
@indyaah w rzeczywistości ta odpowiedź jest nieprawidłowa, istnieje subtelna różnica między katalogiem roboczym użytkownika a bieżącym katalogiem roboczym procesu systemowego (cwd); przez większość czasu „user.dir” wskazuje na cwd procesu (java); ale „user.dir” ma inną semantykę i nie należy go używać do uzyskania cwd procesu Java; btw: istnieje więcej właściwości dostępnych dla procesu java docs.oracle.com/javase/tutorial/essential/environment/… tylko dla odniesienia
comeGetSome
381

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

Za pomocą java.nio.file.Pathi java.nio.file.Pathsmożesz wykonać następujące czynności, aby pokazać, co Java uważa za twoją bieżącą ścieżkę. Działa to od 7 lat i używa NIO.

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

Dane wyjściowe, Current relative path is: /Users/george/NetBeansProjects/Tutorialsktóre w moim przypadku są miejscem, z którego prowadziłem klasę. Konstruowanie ścieżek we względny sposób, nie używając separatora wiodącego do wskazania, że ​​budujesz ścieżkę bezwzględną, wykorzysta tę ścieżkę względną jako punkt początkowy.

geoO
źródło
2
Pierwszy nie jest zaznaczony, ale drugi faktycznie dostanie folder domowy. Nie bieżący katalog roboczy, w którym działa aplikacja.
Peter De Winter
12
Proszę nie mylić katalogu domowego użytkownika („user.home”, / Users / george w twoim przypadku) i bieżącego katalogu roboczego („user.dir”, który będzie katalogiem, z którego uruchomiłeś JVM dla twojej aplikacji , więc może być coś w rodzaju np. / Users / george / workspace / FooBarProject).
David
1
Wolę w ten sposób. Kiedy potrzebuję elementu nadrzędnego katalogu roboczego, to nie działa: Paths.get("").getParent()daje null. Zamiast tego działa: Paths.get("").toAbsolutePath().getParent().
Ole VV
235

Poniższe działa na Javie 7 i nowszych (patrz dokumentacja tutaj ).

import java.nio.file.Paths;

Paths.get(".").toAbsolutePath().normalize().toString();
Dmitrij Bespałow
źródło
11
Jak to jest lepsze niż bardziej przenośne import java.io.File; File(".").getAbsolutePath()?
Evgeni Sergeev
8
Kiedy mówisz przenośny, masz na myśli, że działa w Javie 6 i wcześniejszych wersjach? Paths.get()można uznać za lepszy, ponieważ daje bezpośredni dostęp do bardziej wydajnego Pathinterfejsu.
Ole VV
8
Jaka jest potencjalna zaleta korzystania .normalize()w tym kontekście?
Ole VV
7
@ OleV.V. Z Javadoc: ( metoda normalizacji )Returns a path that is this path with redundant name elements eliminated.
Stephan
W tym przypadku byłby już znormalizowany.
JM Becker
73

To da ci ścieżkę do twojego bieżącego katalogu roboczego:

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

To da ci ścieżkę do pliku o nazwie „Foo.txt” w katalogu roboczym:

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

Edycja: Aby uzyskać bezwzględną ścieżkę do bieżącego katalogu:

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

* Aktualizacja * Aby uzyskać bieżący katalog roboczy:

Path path = FileSystems.getDefault().getPath("").toAbsolutePath();
znak
źródło
11
to po prostu zwraca „.” dla mnie.
john ktejik
3
Tak, w wielu systemach będzie to odwołanie do katalogu roboczego. Aby uzyskać ścieżkę bezwzględną, możesz dodać jeszcze jedno wywołanie metodyPath path = FileSystems.getDefault().getPath(".").toAbsolutePath();
Mark
2
Nie potrzebujesz pliku foo.txt, po prostu wstaw pusty ciąg znaków, aby uzyskać katalog
John Kejik
1
W systemie Windows (10) daje mi to po prostu Pathobiekt wskazujący plik o nazwie .wewnątrz bieżącego działającego katalogu. Używanie pustego ciągu zamiast "."pracować dla mnie.
Kröw,
36

To jest dla mnie rozwiązanie

File currentDir = new File("");
użytkownik2430452
źródło
1
Ma to skutki uboczne, gdy używasz takiego obiektu File jako elementu nadrzędnego innego pliku: nowy plik (nowy plik („”), „podkatalog”) nie będzie działał zgodnie z oczekiwaniami
MRalwasser
13
Aby to naprawić, użyj new File("").getAbsoluteFile()zamiast tego.
MRalwasser
4
Jeśli chodzi o jego wartość, miałem więcej szczęścia z File („.”).
keshlam
Jak zdefiniować ścieżkę względną w Javie Ta strona pomogła mi. Przyjąłem również, że powinienem użyć tego /przy tworzeniu ścieżki względnej. Myliłem się, nie zaczynaj /. ../działa również przy przechodzeniu do góry w drzewie katalogów.
Irrationalkilla,
@keshlam To dało mi plik w bieżącym katalogu o nazwie ..
Kröw
32

Znalazłem to rozwiązanie w komentarzach, które jest lepsze niż inne i bardziej przenośne:

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

Lub nawet

String cwd = Paths.get("").toAbsolutePath();
freedev
źródło
Jest to dokładnie to samo, co odpowiedź comeGetSome i tak naprawdę jest to Java <7
GoGoris
30

Co sprawia, że ​​myślisz, że c: \ windows \ system32 nie jest twoim bieżącym katalogiem? user.dirNieruchomość jest wyraźnie będzie „bieżący katalog roboczy użytkownika”.

Innymi słowy, chyba że uruchamiasz Javę z wiersza poleceń, c: \ windows \ system32 prawdopodobnie jest twoją CWD. Oznacza to, że jeśli klikniesz dwukrotnie, aby uruchomić program, prawdopodobnie nie będzie katalogu, z którego klikniesz dwukrotnie.

Edycja : Wygląda na to, że dotyczy to tylko starych wersji Windows i / lub Java.

Paul Wagland
źródło
2
Nie wydaje się to prawdą, przynajmniej nie na moim komputerze z systemem Windows 7 używającym Java 7. user.dirjest to folder, w którym dwukrotnie kliknąłem plik jar.
Jolta,
26

Zastosowanie CodeSource#getLocation().

Działa to również dobrze w plikach JAR. Możesz uzyskać CodeSourceprzez, ProtectionDomain#getCodeSource()a z ProtectionDomainkolei można uzyskać przez 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
źródło
2
Zwraca to lokalizację pliku JAR. Nie o to poproszono.
user207421,
22
this.getClass().getClassLoader().getResource("").getPath()
Peter De Winter
źródło
12
Zgłasza NPE, gdy uruchamiam aplikację z pliku JAR, klikając go dwukrotnie.
Matthew Wise,
2
Zwraca to, ""jeśli aplikacja działa z pliku JAR lub elementu CLASSPATH. Nie o to poproszono.
user207421,
@ Zizouz212 getClass()jest metodą obiektową, więc w kontekście statycznym samo usunięcie thisnie działa. Musiałbyś wyraźnie odnieść się do klasy, w której uczestniczysz MyClass.class.getClassLoader()......
Kröw
Niemniej jednak nie zwróci katalogu roboczego ...
Angel O'Sphere
18

ogólnie jako obiekt File:

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

możesz chcieć mieć pełny ciąg znaków, taki jak „D: / a / b / c” wykonujący:

getCwd().getAbsolutePath()
chodź weź trochę
źródło
1
Działa to dobrze w testach Androida, ponieważ Android nie zawiera java.nio.file.Files.
iamreptar
Wydaje się, że nie działa dla mnie w kontekście statycznym (nowy plik („”) zgłasza wyjątek NullPointerException) ..?
nsandersen
2
@nsandersen prawdopodobnie użyłeś niewłaściwego obiektu File: System.out.println (new java.io.File (""). getAbsolutePath ());
comeGetSome
5

W systemie Linux po uruchomieniu pliku jar z terminala oba zwrócą to samo String: „/ home / CurrentUser” , bez względu na to, gdzie znajduje się plik jar. Zależy to tylko od tego, jakiego bieżącego katalogu używasz z terminalem podczas uruchamiania pliku jar.

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

System.getProperty("user.dir");

Jeśli twoja Classz mainzostanie wywołana MainClass, spróbuj:

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

Będzie to zwróci Stringz bezwzględną ścieżkę do jar pliku.

Jan Povolný
źródło
3
O co nie prosiliśmy.
user207421,
5

Użycie Windows user.dir zwraca katalog zgodnie z oczekiwaniami, ale NIE przy uruchamianiu aplikacji z podwyższonymi uprawnieniami (działającymi jako administrator), w takim przypadku otrzymujesz C: \ WINDOWS \ system32

SijeDeHaan
źródło
3

Mam nadzieję, że chcesz uzyskać dostęp do bieżącego katalogu wraz z pakietem, tj. Jeśli Twój program Java jest już włączony c:\myApp\com\foo\src\service\MyTest.javai chcesz wydrukować do c:\myApp\com\foo\src\servicetego czasu , możesz wypróbować następujący kod:

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

Uwaga: ten kod jest testowany tylko w systemie Windows z Oracle JRE.

JSS
źródło
6
Byłoby słusznie nie głosować za tą odpowiedzią. Zastanów się, zanim opublikujesz. Twój kod jest uszkodzony, chyba że wszystkie są prawdziwe: 1. JRE należy do Oracle, w przeciwnym razie nie będzie właściwości systemowej „sun.java.command” → NPE; 2. System operacyjny to Windows (użyj File.separatorzamiast lub konstruktor z wieloma argumentami File); 3. ścieżka klasy jest określona w wierszu poleceń, a „bieżący katalog zawierający pakiet” (??) to: a. określone najpierw, b. określone absolutnie, c. dokładnie pasuje do CWD (nawet przy braku rozróżniania wielkości liter w systemie Windows) oraz d. jest potomkiem CWD
Michael Scheper
Dotyczy to punktów 1 i 2. Ale chyba, że ​​czegoś mi brakuje, nadal polegasz na ścieżce klasy określonej w wierszu poleceń (tj. Nie w zmiennej środowiskowej), a dla „bieżącego katalogu zawierającego pakiet” (I przyznaję, że tak naprawdę nie rozumiem, co przez to rozumiesz) bycia potomkiem konkretnie pierwszego elementu w ścieżce klas. Problem z dopasowywaniem spraw pozostaje. Przepraszam, jeśli mój komentarz nie był pomocny; Poświęciłem jasność, aby zachować limit znaków komentujących.
Michael Scheper,
@Inversus, „działa idealnie” tylko w niektórych środowiskach; akurat miałeś szczęście, by to sprawdzić. Pisanie oprogramowania, które zawodzi w uzasadnionych środowiskach wykonawczych, nie jest dobrą praktyką, nawet jeśli zestaw środowisk testowych nie jest wystarczająco rozbudowany, aby je uwzględnić.
Charles Duffy,
@CharlesDuffy Masz rację, to nie jest dobra praktyka. Na szczęście to rozwiązanie „rozwiązujące mój konkretny problem” nie spowodowało, że „[zawodzi] w legalnych środowiskach wykonawczych”. W rzeczywistości pomogło mi to rozwiązać taką awarię i napisać bardziej solidny kod, oprócz rozwiązania bardzo konkretnego problemu, który miałem (który był tylko w pewnym stopniu związany z tym pytaniem / odpowiedzią). Chyba miałem szczęście go znaleźć.
Inversus
3

Wspomnij, że jest sprawdzany tylko w, Windowsale myślę, że działa idealnie na innych systemach operacyjnych [ Linux,MacOs,Solaris] :).


Miałem 2 .jar pliki w tym samym katalogu. Chciałem, aby z jednego .jarpliku uruchomić drugi .jarplik, który znajduje się w tym samym katalogu.

Problem polega na tym, że po uruchomieniu z cmdbieżącego katalogu jest system32.


Ostrzeżenia!

  • Poniższe wydaje się działać całkiem dobrze we wszystkich testach, które przeprowadziłem, nawet z nazwą folderu ;][[;'57f2g34g87-8+9-09!2#@!$%^^&()lub ()%&$%^@# działa dobrze.
  • Korzystam ProcessBuilderz poniższych poniżej:

🍂 ..

//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
źródło
Zwraca to lokalizację pliku JAR. Nie o to poproszono.
user207421,
@EJP Lokalizacja pliku .jar nie jest bieżącym katalogiem roboczym programu Java?
GOXR3PLUS,
2

Bieżący katalog roboczy jest różnie zdefiniowany w różnych implementacjach Java. W przypadku niektórych wersji wcześniejszych niż Java 7 nie było spójnego sposobu uzyskania katalogu roboczego. Można obejść ten problem, uruchamiając plik Java -Di definiując zmienną do przechowywania informacji

Coś jak

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

To nie do końca prawda, ale masz pomysł. Więc System.getProperty("com.mycompany.workingDir")...

MJB
źródło
6
Nie dotyczy pytania.
Peter De Winter
1
Ma to znaczenie dla Javy - jest to lokalizacja na dysku, do której odnoszą się pliki otwierane za pomocą względnych ścieżek.
Rob I
2
Tak, to ma sens. Moje słowa były nieco źle wybrane. Ale nie rozumiesz sedna - przed Javą 7 nie było sposobu, aby poznać aktualny katalog roboczy, a różne implementacje ustawiają je ... inaczej ...
MJB,
1

Załóżmy, że próbujesz uruchomić swój projekt w środowisku Eclipse lub w sieci lub samodzielnie z wiersza poleceń. Mam sposób, aby to naprawić

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

Aby użyć wszędzie tam, gdzie chcesz uzyskać podstawową ścieżkę do odczytu pliku, możesz przekazać klasę zakotwiczenia do powyższej metody, wynik może być tym, czego potrzebujesz: D

Najlepsza,

Bachden
źródło
2
Zwraca to lokalizację pliku JAR. Nie o to poproszono.
user207421,
@ user207421 tak Wiem, że ta odpowiedź nie jest prawdziwą odpowiedzią na pytanie, ale przez większość czasu wszyscy chcą uzyskać „katalog, w którym znajdują się słoiki”, zamiast „katalogu roboczego wiersza poleceń”.
bachden
0

Żadna z zamieszczonych tutaj odpowiedzi nie działała dla mnie. Oto, co zadziałało:

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

Edycja: Ostateczna wersja w moim kodzie:

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()
Czcigodni Agenci
źródło
Zwraca to lokalizację pliku JAR. Nie o to poproszono.
user207421,
0

To jest moja srebrna kula, kiedy tylko pojawia się moment pomieszania. (Nazwij to przede wszystkim). Może na przykład JVM ma inną wersję IDE. Ta funkcja statyczna wyszukuje bieżący PID procesu i otwiera VisualVM na tym pid. Zamieszanie kończy się tutaj, ponieważ chcesz tego wszystkiego i dostajesz to ...

  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
źródło
-6

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

Marko Stojkovic
źródło
-7

to jest nazwa bieżącego katalogu

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

to jest bieżąca ścieżka do katalogu

String path=folder.getPath();
Prasad De Silva
źródło
1
OP chciał aktualny katalog roboczy, z którego uruchomiono aplikację.
Leif Gruenwoldt
To jest twój katalog domowy , a nie bieżący katalog roboczy, z wyjątkiem twojego. Nie o to poproszono.
user207421,