Jak uzyskać aktualny katalog roboczy w Javie?

112

Powiedzmy, że mam swoją główną klasę C:\Users\Justian\Documents\. Jak mogę sprawić, by mój program pokazał, że jest dostępny C:\Users\Justian\Documents?

Hard-Coding nie wchodzi w grę - musi być przystosowalne, jeśli zostanie przeniesione w inne miejsce.

Chcę zrzucić kilka plików CSV do folderu, poprosić program o rozpoznanie wszystkich plików, a następnie załadować dane i manipulować nimi. Naprawdę chcę tylko wiedzieć, jak przejść do tego folderu.

Justian Meyer
źródło
1
spójrz na ten artykuł .
Matthew J Morrison
1
A co jeśli twoja główna klasa znajduje się w pliku jar? Jakiego wyniku chciałbyś wtedy?
Mattias Nilsson
1
Dlaczego w ogóle miałbyś to robić?
Ed S.
1
brzmi tak, jakbyś potrzebował katalogu, w którym znajdują się pliki CSV, i niech plik .jar będzie mógł odwoływać się do tego katalogu, zobacz moją odpowiedź, jeśli tak jest.

Odpowiedzi:

149

Jednym ze sposobów byłoby użycie właściwości systemowej, System.getProperty("user.dir"); która da ci „Bieżący katalog roboczy, kiedy właściwości zostały zainicjowane”. Prawdopodobnie tego chcesz. aby dowiedzieć się, gdzie javapolecenie zostało wydane, w twoim przypadku w katalogu z plikami do przetworzenia, nawet jeśli rzeczywisty plik .jar może znajdować się gdzie indziej na komputerze. Posiadanie katalogu z rzeczywistym plikiem .jar nie jest przydatne w większości przypadków.

Poniższe polecenia wydrukują bieżący katalog, z którego polecenie zostało wywołane, niezależnie od tego, gdzie znajduje się plik .class lub .jar, w którym znajduje się plik .class.

public class Test
{
    public static void main(final String[] args)
    {
        final String dir = System.getProperty("user.dir");
        System.out.println("current dir = " + dir);
    }
}  

jeśli jesteś w programie, /User/me/a plik .jar zawierający powyższy kod jest w /opt/some/nested/dir/ poleceniu java -jar /opt/some/nested/dir/test.jar Test, wyświetli się current dir = /User/me.

Jako bonus powinieneś również przyjrzeć się używaniu dobrego obiektowego parsera argumentów wiersza poleceń. Bardzo polecam JSAP , Java Simple Argument Parser. Umożliwiłoby to użycie System.getProperty("user.dir")i alternatywnie przekazanie czegoś innego, aby zastąpić to zachowanie. O wiele łatwiejsze w utrzymaniu rozwiązanie. To sprawiłoby, że przekazywanie do katalogu w celu przetworzenia byłoby bardzo łatwe do wykonania i user.dirgdyby nic nie zostało przekazane , można by do niego wrócić .


źródło
Przetestuję to, kiedy będę mógł. Jestem naprawdę zajęty tym problemem .jar: P
Justian Meyer
czy odwiedziłeś link w mojej odpowiedzi na ten problem .jar, gdzie pokazuję, jak zbudować plik .jar za pomocą ANT?
Kod z Jarroda, który zwraca bezwzględną ścieżkę bieżącego katalogu roboczego z właściwości systemu, user.dirjest bardzo łatwy w użyciu. System.getProperty ("user.dir");
74

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

Aktualizacja zgodnie z komentarzem PO:

Chcę zrzucić kilka plików CSV do folderu, poprosić program o rozpoznanie wszystkich plików, a następnie załadować dane i manipulować nimi. Naprawdę chcę tylko wiedzieć, jak przejść do tego folderu.

Wymagałoby to zakodowania / znajomości ich względnej ścieżki w programie. Zamiast tego rozważ dodanie jego ścieżki do ścieżki klas, aby można było użyćClassLoader#getResource()

File classpathRoot = new File(classLoader.getResource("").getPath());
File[] csvFiles = classpathRoot.listFiles(new FilenameFilter() {
    @Override public boolean accept(File dir, String name) {
        return name.endsWith(".csv");
    }
});

Lub przekazać swoją ścieżkę jako main()argument.

BalusC
źródło
3
+1. Jest kilka warunków, aby to zadziałało; najważniejsze jest to, że twoja "główna klasa" jest ładowana z systemu plików. W Javie nie jest niczym niezwykłym, że to założenie jest fałszywe. Ale, jeśli jesteś pewien, że ładujesz swoją klasę z słoik na systemie plików, to metoda, która działa.
erickson
Tak naprawdę wszystko zależy. Ja próbuje dostać mój JAR skompilować, ale to osobny problem w tej chwili. Jeśli uważasz, że możesz w tym pomóc, odwiedź: stackoverflow.com/questions/3152240/… . Jestem pewien, że opublikowanie tego jest wykroczeniem, ale ma to związek z tym problemem. Jeśli uda mi się to naprawić, na pewno będzie to moja odpowiedź.
Justian Meyer
Dlaczego miałbym to zakodować? Robiłem już podobne rzeczy. Załóżmy, że mój jar i folder zawsze będą miały podobną relację (tj. W tym samym katalogu). Jeśli to prawda, mógłbym uzyskać katalog jar, a następnie zmodyfikować go, aby znaleźć folder.
Justian Meyer
Jeśli znajduje się w tym samym folderze, co plik JAR, oznacza to, że jest już w ścieżce klas. Słowo „kodowanie na stałe” jest nieco przesadzone, tak naprawdę miałem na myśli „znajomość ich ścieżki w stosunku do pliku JAR”.
BalusC
1
@Moebius: Hę? Czy jesteś nowy w Javie? Sprawdź javadoc . Po prostu użyj dokładnie tego, co zwrócone przez getLocation()metodę. Inne oczywiście nie będą działać.
BalusC
31
File currentDirectory = new File(new File(".").getAbsolutePath());
System.out.println(currentDirectory.getCanonicalPath());
System.out.println(currentDirectory.getAbsolutePath());

Drukuje coś takiego:

/path/to/current/directory
/path/to/current/directory/.

Zwróć uwagę, że File.getCanonicalPath()zgłasza sprawdzony IOException, ale usunie takie rzeczy, jak ../../../

cyber-mnich
źródło
13
this.getClass().getClassLoader().getResource("").getPath()
Peter De Winter
źródło
zwróć uwagę, że zwróci to ścieżkę do „bin / classes /”, a nie tylko do „bin”.
programista Androida
podczas debugowania działającej aplikacji przy użyciu Intellij Idea, zwróciło to „/C:/Program%20Files/Java/jdk1.8.0_112/:”
prędkość
5

Właśnie użyłem:

import java.nio.file.Path;
import java.nio.file.Paths;

...

Path workingDirectory=Paths.get(".").toAbsolutePath();
user3696181
źródło
9
Twój nie działa, to jest poprawnePaths.get("").toAbsolutePath();
To Kra
@ ToKra Jeśli Paths.get("my/file").toAbsolutePath()dostanę /my/file, co na pewno nie jest cwd.
abergmeier
1
@abergmeier Napisałem „” w ciągu znaków, a nie „mój / plik”
do Kra
5

Jeśli chcesz uzyskać bieżący katalog roboczy, użyj następującego wiersza

System.out.println(new File("").getAbsolutePath());
rjrajsaha
źródło
4

Jeśli chcesz mieć bezwzględną ścieżkę obecnego kodu źródłowego, moja sugestia jest taka:

String internalPath = this.getClass().getName().replace(".", File.separator);
String externalPath = System.getProperty("user.dir")+File.separator+"src";
String workDir = externalPath+File.separator+internalPath.substring(0, internalPath.lastIndexOf(File.separator));
jmamatos
źródło
To nie działa, gdy uruchamiasz go w IDE lub używasz czegoś do obracania instancji.
Sarp Kaya,
Ścieżka wewnętrzna to java \ lang \ Class Ścieżka zewnętrzna to E: \ BranchProduction1.4.0 \ FilesTestProject \ src Katalog roboczy to E: \ BranchProduction1.4.0 \ FilesTestProject \ src \ java \ lang czy możesz wyjaśnić wynik?
JAVA
3

Kto powiedział, że twoja główna klasa jest w pliku na lokalnym dysku twardym? Klasy są częściej umieszczane w plikach JAR i czasami ładowane przez sieć, a nawet generowane w locie.

Więc co tak naprawdę chcesz robić? Prawdopodobnie istnieje sposób, aby to zrobić, który nie zakłada założeń, skąd pochodzą klasy.

Michael Borgwardt
źródło
Chcę zrzucić kilka plików CSV do folderu, poprosić program o rozpoznanie wszystkich plików, a następnie załadować dane i manipulować nimi. Naprawdę chcę tylko wiedzieć, jak przejść do tego folderu.
Justian Meyer
Może czegoś mi brakuje, ale wygląda na to, że absolutna ścieżka zadziała. Powiedziałeś, że nie możesz tego na stałe zakodować, ale skąd masz wiedzieć, w którym folderze zajrzeć na początek?
Chris Thompson,
Problem w tym, że chcę go przenieść na inne komputery, nie tylko na swój własny. Nie rozumiem, jak twarde kodowanie ścieżki mogłoby działać. „Załóżmy, że mój jar i folder zawsze będą miały podobną relację (tj. W tym samym katalogu). Gdyby to było prawdą, mógłbym uzyskać katalog jar, a następnie zmodyfikować go, aby znaleźć folder”. Jedyny sposób, w jaki mógłbym go zakodować, to gdybym nie musiał uwzględniać pełnej ścieżki z dysku twardego do pliku. Może uda mi się cofnąć tylko 3 foldery (tj. „Dokumenty \ Projekt \ Zrzut \ [plik / folder]”)
Justian Meyer
Powiedziałbym, że chcesz uzyskać uchwyt do katalogu, w którym znajduje się plik jar. Czy spełniłoby to Twoje wymagania?
Chris Thompson,