Łączenie ścieżek w Javie


99

W Pythonmogę połączyć dwie ścieżki za pomocą os.path.join:

os.path.join("foo", "bar") # => "foo/bar"

Próbuję osiągnąć to samo w Javie, nie martwiąc się, czy tak OSjest Unix, Solarisczy Windows:

public static void main(String[] args) {
    Path currentRelativePath = Paths.get("");
    String current_dir = currentRelativePath.toAbsolutePath().toString();
    String filename = "data/foo.txt";
    Path filepath = currentRelativePath.resolve(filename);

    // "data/foo.txt"
    System.out.println(filepath);

}

Spodziewałem się, Path.resolve( )że dołączy to do mojego obecnego katalogu /home/user/testz data/foo.txttworzeniem /home/user/test/data/foo.txt. Co się mylę?


1
to może być coś, czego nie widzę. Twoja aktualna ścieżka to „”. Twoja druga ścieżka to „data / foo.txt”. Może twoim problemem jest to, że wydaje się, że drukujesz obiekt Path zamiastfilepath.toString()
cjds

2
Użyjnew File(parent, child)
saka1029,

Odpowiedzi:


100

Mimo oryginalnego rozwiązania dla coraz aktualny katalog używając empty Stringprace. Ale zaleca się użycie user.dirwłaściwości dla katalogu bieżącego i user.homekatalogu domowego.

Path currentPath = Paths.get(System.getProperty("user.dir"));
Path filePath = Paths.get(currentPath.toString(), "data", "foo.txt");
System.out.println(filePath.toString());

wynik:

/Users/user/coding/data/foo.txt

Z dokumentacji klasy Java Path :

Ścieżka jest uważana za pustą ścieżką, jeżeli składa się wyłącznie z jednego elementu, który jest nazwa empty. Dostęp do pliku przy użyciu empty path is equivalent to accessing the default directorysystemu plików.


Dlaczego Paths.get("").toAbsolutePath()działa

Gdy do elementu przekazywany jest pusty ciąg Paths.get(""), zwracany Pathobiekt zawiera pustą ścieżkę. Ale kiedy wywołujemy Path.toAbsolutePath(), sprawdza, czy długość ścieżki jest większa niż zero, w przeciwnym razie używa user.dirwłaściwości systemowej i zwraca bieżącą ścieżkę.

Oto kod implementacji systemu plików Unix: UnixPath.toAbsolutePath ()


Zasadniczo Pathpo rozwiązaniu bieżącej ścieżki katalogu należy ponownie utworzyć instancję.

Sugerowałbym również użycie File.separatorChardla kodu niezależnego od platformy.

Path currentRelativePath = Paths.get("");
Path currentDir = currentRelativePath.toAbsolutePath(); // <-- Get the Path and use resolve on it.
String filename = "data" + File.separatorChar + "foo.txt";
Path filepath = currentDir.resolve(filename);

// "data/foo.txt"
System.out.println(filepath);

Wynik:

/Users/user/coding/data/foo.txt

Nie ja, może ktoś myśli o pracy na łańcuchach i separatorCharjest gorszy od jakiejś „abstrakcji wyższego poziomu”, coś, co wygląda jakPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575,

22

Paths#get(String first, String... more) stany,

Konwertuje ciąg ścieżki lub sekwencję ciągów, które po połączeniu tworzą ciąg ścieżki na plik Path.

...

A Pathreprezentująca pustą ścieżkę jest zwracana, jeśli pierwsza jest pustym ciągiem, a more nie zawiera żadnych niepustych ciągów.

Aby uzyskać aktualny katalog użytkownika, możesz po prostu użyć System.getProperty("user.dir").

Path path = Paths.get(System.getProperty("user.dir"), "abc.txt");
System.out.println(path);

Ponadto getmetoda używa argumentu o zmiennej długościString , który będzie używany do dostarczania kolejnych ciągów ścieżek. Tak więc, aby stworzyć Pathdla /test/inside/abc.txttrzeba użyć go w następujący sposób,

Path path = Paths.get("/test", "inside", "abc.txt");

11

Nie jest to konkretna metoda.

Jeśli używasz języka Java 8 lub nowszego, masz 2 opcje:

a) Użyj java.util.StringJoiner

StringJoiner joiner = new StringJoiner(File.pathSeparator); //Separator
joiner.add("path1").add("path2");
String joinedString = joiner.toString();

b) Użyj String.join(File.pathSeparator, "path1", "path2");

Jeśli używasz java 7 lub starszej, możesz użyć biblioteki commons-lang z apache commons. Klasa StringUtils ma metodę łączenia łańcuchów za pomocą separatora.

do) StringUtils.join(new Object[] {"path1", "path2"}, File.pathSeparator);

Uwaga dodatkowa: możesz użyć linuxowego separatora ścieżek „/” dla okien (pamiętaj tylko, że ścieżki bezwzględne to coś w rodzaju „/ C: / mydir1 / mydir2”. Używanie zawsze „/” jest bardzo przydatne, jeśli używasz protokołów takich jak file: //


StringJoiner zwrócił mi/home/user/test:foo.txt
cybertextron

Opcje, które znasz, nie są jedynymi istniejącymi. Można na przykład użyć StringBuildera zamiast łącznika. W rzeczywistości twoja implementacja oparta na ciągach znaków, a nie na plikach / ścieżkach, jest dość naiwna i prowadziłaby do problemów w wielu scenariuszach.
XenoRo,

2
File.separatorpracował dla mnie zamiastFile.pathSeparator
Evan Siroky

użyj Pathes.get ("path1", "path2"). toAbsolutePath (). toString ()
Erdinc Ay

6

Najbardziej podstawowym sposobem jest:

Path filepath = Paths.get("foo", "bar");

Nigdy nie powinieneś pisać Paths.get(""). Dziwię się, że to w ogóle działa. Jeśli chcesz jawnie odwołać się do bieżącego katalogu, użyj Paths.get(System.getProperty("user.dir")). Jeśli chcesz mieć katalog domowy użytkownika, użyj Paths.get(System.getProperty("user.home")).

Możesz także połączyć te podejścia:

Path filepath = Paths.get(
    System.getProperty("user.home"), "data", "foo.txt");

1

Najbardziej niezawodnym, niezależnym od platformy sposobem łączenia ścieżek w Javie jest użycie Path::resolve(jak wspomniano w JavaDoc dla Paths::get). W przypadku tablicy ciągów o dowolnej długości reprezentującej fragmenty ścieżki można je połączyć za pomocą strumienia Java:

private static final String[] pieces = {
    System.getProperty("user.dir"),
    "data",
    "foo.txt"};
public static void main (String[] args) {
    Path dest = Arrays.stream(pieces).reduce(
    /* identity    */ Paths.get(""),
    /* accumulator */ Path::resolve,
    /* combiner    */ Path::resolve);
    System.out.println(dest);
}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.