Unione di percorsi in Java


99

In Pythonposso unire due percorsi con os.path.join:

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

Sto cercando di ottenere lo stesso risultato in Java, senza preoccuparmi se OSè Unix, Solariso 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);

}

Mi aspettavo che Path.resolve( )si unisse alla mia directory attuale /home/user/testcon data/foo.txtmaking /home/user/test/data/foo.txt. Cosa sto sbagliando?


1
questo potrebbe essere qualcosa che non vedo. Il tuo percorso attuale è "". Il tuo secondo percorso è "data / foo.txt". Forse il tuo problema è che sembri stampare un oggetto Path invece difilepath.toString()
cjds

2
Usanew File(parent, child)
saka1029

Risposte:


99

Anche se la soluzione originale per ottenere la directory corrente utilizzando il file empty Stringworks. Ma si consiglia di utilizzare la user.dirproprietà per la directory corrente e user.homeper la directory home.

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

produzione:

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

Dalla documentazione della classe Java Path :

Un percorso è considerato un percorso vuoto se è costituito esclusivamente da un elemento nome che è empty. Accesso a un file utilizzando un empty path is equivalent to accessing the default directoryfile system.


Perché Paths.get("").toAbsolutePath()funziona

Quando una stringa vuota viene passata a Paths.get(""), l' Pathoggetto restituito contiene un percorso vuoto. Ma quando chiamiamo Path.toAbsolutePath(), controlla se la lunghezza del percorso è maggiore di zero, altrimenti utilizza la user.dirproprietà di sistema e restituisce il percorso corrente.

Ecco il codice per l'implementazione del file system Unix: UnixPath.toAbsolutePath ()


Fondamentalmente è necessario creare Pathnuovamente l' istanza una volta risolto il percorso della directory corrente.

Inoltre suggerirei di utilizzare File.separatorCharper il codice indipendente dalla piattaforma.

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

Produzione:

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

Non io, forse qualcuno pensa che lavorare sulle corde separatorCharsia inferiore a qualche "astrazione di livello superiore", qualcosa che assomiglia aPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575

22

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

Converte una stringa di percorso o una sequenza di stringhe che quando unite formano una stringa di percorso in un file Path.

...

Viene restituito Pathun percorso che rappresenta un vuoto se il primo è la stringa vuota e altro non contiene stringhe non vuote.

Per ottenere la directory utente corrente puoi semplicemente usare System.getProperty("user.dir").

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

Inoltre, il getmetodo utilizza l' argomento di lunghezza variabile di String, che verrà utilizzato per fornire le stringhe di percorso successive. Quindi, per creare Pathper /test/inside/abc.txtte devi usarlo in un modo seguente,

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

11

Non è un metodo specifico.

Se usi java 8 o superiore, hai 2 opzioni:

a) Usa java.util.StringJoiner

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

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

Se usi java 7 o versioni precedenti, puoi usare la libreria commons-lang di apache commons. La classe StringUtils dispone di un metodo per unire le stringhe utilizzando un separatore.

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

Una nota a margine: puoi usare il separatore di percorsi linux "/" per windows (ricorda solo che i percorsi assoluti sono qualcosa come "/ C: / miadir1 / miadir2". Usare sempre "/" è molto utile se usi protocolli come file: //


StringJoiner mi ha restituito/home/user/test:foo.txt
cybertextron

Le opzioni che conosci non sono le uniche esistenti. Si potrebbe usare StringBuilder invece di joiner, per esempio. E in effetti, la tua implementazione basata su stringhe piuttosto che su file / percorsi è piuttosto ingenua e porterebbe a problemi in molti scenari.
XenoRo

2
File.separatorha funzionato per me invece diFile.pathSeparator
Evan Siroky

usa Pathes.get ("path1", "path2"). toAbsolutePath (). toString ()
Erdinc Ay,

5

Il modo più semplice è:

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

Non dovresti mai scrivere Paths.get(""). Sono sorpreso che funzioni affatto. Se vuoi fare riferimento esplicitamente alla directory corrente, usa Paths.get(System.getProperty("user.dir")). Se vuoi la home directory dell'utente, usa Paths.get(System.getProperty("user.home")).

Puoi anche combinare gli approcci:

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

1

Il modo più affidabile e indipendente dalla piattaforma per unire i percorsi in Java è utilizzare Path::resolve(come indicato in JavaDoc per Paths::get). Per un array di stringhe di lunghezza arbitraria che rappresenta parti di un percorso, queste potrebbero essere unite insieme utilizzando un Java Stream:

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

1

Puoi fare mi piace

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

Un buon post dettagliato è qui Path Sample Usecase

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.