Verbinden von Pfaden in Java

99

In Pythonkann ich zwei Pfade verbinden mit os.path.join:

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

Ich versuche, dasselbe in Java zu erreichen, ohne mir Sorgen zu machen, ob dies der Fall OSist Unix, Solarisoder 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);

}

Ich habe erwartet , dass Path.resolve( )würde mein aktuelles Verzeichnis verbindet /home/user/testmit data/foo.txtmachen /home/user/test/data/foo.txt. Was mache ich falsch?

Cybertextron
quelle
1
Das könnte etwas sein, was ich nicht sehe. Ihr aktueller Pfad ist "". Ihr zweiter Pfad ist "data / foo.txt". Vielleicht ist Ihr Problem, dass Sie scheinbar ein Path-Objekt anstelle vonfilepath.toString()
cjds
2
Verwenden Sienew File(parent, child)
saka1029

Antworten:

99

Auch wenn die ursprüngliche Lösung zum Abrufen des aktuellen Verzeichnisses empty Stringfunktioniert. Es wird jedoch empfohlen, die user.dirEigenschaft für das aktuelle Verzeichnis und user.homefür das Ausgangsverzeichnis zu verwenden.

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

Ausgabe:

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

Aus der Java Path- Klasse Dokumentation:

Ein Pfad wird als leerer Pfad betrachtet, wenn er nur aus einem Namenselement besteht empty. Zugriff auf eine Datei über ein empty path is equivalent to accessing the default directoryDateisystem.


Warum Paths.get("").toAbsolutePath()funktioniert

Wenn eine leere Zeichenfolge an übergeben wird Paths.get(""), Pathenthält das zurückgegebene Objekt einen leeren Pfad. Beim Aufruf Path.toAbsolutePath()wird jedoch geprüft, ob die Pfadlänge größer als Null ist. Andernfalls werden die user.dirSystemeigenschaften verwendet und der aktuelle Pfad zurückgegeben.

Hier ist der Code für die Implementierung des Unix-Dateisystems: UnixPath.toAbsolutePath ()


Grundsätzlich müssen Sie die PathInstanz erneut erstellen , sobald Sie den aktuellen Verzeichnispfad aufgelöst haben.

Außerdem würde ich vorschlagen, File.separatorCharplattformunabhängigen Code zu verwenden.

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

Ausgabe:

/Users/user/coding/data/foo.txt
YoungHobbit
quelle
Nicht ich, vielleicht denkt jemand, dass er an Strings arbeitet und separatorChareiner "Abstraktion auf höherer Ebene" unterlegen ist, etwas, das aussiehtPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575
22

Paths#get(String first, String... more) Zustände,

Konvertiert eine Pfadzeichenfolge oder eine Folge von Zeichenfolgen , die beim Verbinden eine Pfadzeichenfolge bilden, in a Path.

...

Eine PathDarstellung eines leeren Pfads wird zurückgegeben, wenn zuerst die leere Zeichenfolge ist und more keine nicht leeren Zeichenfolgen enthält.

Um das aktuelle Benutzerverzeichnis abzurufen, können Sie einfach verwenden System.getProperty("user.dir").

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

Darüber hinaus getverwendet die Methode das Argument variabler Länge von String, mit dem nachfolgende Pfadzeichenfolgen bereitgestellt werden. Um Pathfür /test/inside/abc.txtSie zu erstellen , müssen Sie es folgendermaßen verwenden:

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

Keine bestimmte Methode.

Wenn Sie Java 8 oder besser verwenden, haben Sie zwei Möglichkeiten:

a) Verwenden Sie java.util.StringJoiner

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

b) Verwenden String.join(File.pathSeparator, "path1", "path2");

Wenn Sie Java 7 oder niedriger verwenden, können Sie die commons-lang-Bibliothek von apache commons verwenden. Die Klasse StringUtils verfügt über eine Methode zum Verknüpfen von Zeichenfolgen mithilfe eines Trennzeichens.

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

Nebenbemerkung: Sie können den Linux-Pfadtrenner "/" für Windows verwenden (Denken Sie daran, dass absolute Pfade etwa "/ C: / mydir1 / mydir2" sind. Die Verwendung von "/" ist sehr nützlich, wenn Sie Protokolle wie file: // verwenden

Rober2D2
quelle
StringJoiner gab mich zurück/home/user/test:foo.txt
Cybertextron
Die Optionen, die Sie kennen, sind nicht die einzigen, die es gibt. Man könnte zum Beispiel StringBuilder anstelle von Joiner verwenden. Tatsächlich ist Ihre Implementierung basierend auf Strings und nicht auf Dateien / Pfaden ziemlich naiv und würde in vielen Szenarien zu Problemen führen.
XenoRo
2
File.separatorarbeitete für mich stattFile.pathSeparator
Evan Siroky
benutze Pathes.get ("path1", "path2"). toAbsolutePath (). toString ()
Erdinc Ay
5

Der grundlegendste Weg ist:

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

Du solltest niemals schreiben Paths.get(""). Ich bin überrascht, dass das überhaupt funktioniert. Wenn Sie explizit auf das aktuelle Verzeichnis verweisen möchten, verwenden Sie Paths.get(System.getProperty("user.dir")). Wenn Sie das Home-Verzeichnis des Benutzers möchten, verwenden Sie Paths.get(System.getProperty("user.home")).

Sie können auch die folgenden Ansätze kombinieren:

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

Die zuverlässigste und plattformunabhängigste Methode zum Verbinden von Pfaden in Java ist die Verwendung von Path::resolve(wie im JavaDoc für angegeben Paths::get). Für ein Array von Strings beliebiger Länge, die Teile eines Pfads darstellen, können diese mithilfe eines Java-Streams zusammengefügt werden:

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);
}
Patrick Parker
quelle
1

Sie können gerne tun

// /root
Path rootPath = Paths.get("/root");
// /root/temp
Path temPath = rootPath.resolve("temp");

Ein guter ausführlicher Beitrag ist hier Path Sample Usecase

Robin Mathur
quelle