Rejoindre des chemins en Java

99

Dans Pythonje peux joindre deux chemins avec os.path.join:

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

J'essaye d'obtenir la même chose en Java, sans me soucier si OSc'est Unix, Solarisou 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);

}

Je m'attendais à ce que Path.resolve( )cela rejoigne mon répertoire actuel /home/user/testavec data/foo.txtmaking /home/user/test/data/foo.txt. Qu'est-ce que je me trompe?

cybertextron
la source
1
c'est peut-être quelque chose que je ne vois pas. Votre chemin actuel est "". Votre deuxième chemin est "data / foo.txt". Peut-être que votre problème est que vous semblez imprimer un objet Path au lieu defilepath.toString()
cjds
2
Utilisationnew File(parent, child)
saka1029

Réponses:

100

Même si la solution originale pour obtenir le répertoire actuel en utilisant les empty Stringœuvres. Mais il est recommandé d'utiliser la user.dirpropriété pour le répertoire courant et user.homepour le répertoire personnel.

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

production:

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

À partir de la documentation de la classe Java Path :

Un chemin est considéré comme un chemin vide s'il se compose uniquement d'un élément de nom qui l'est empty. Accéder à un fichier à l'aide d'un empty path is equivalent to accessing the default directorydu système de fichiers.


Pourquoi ça Paths.get("").toAbsolutePath()marche

Lorsqu'une chaîne vide est transmise à Paths.get(""), l' Pathobjet renvoyé contient un chemin vide. Mais lorsque nous appelons Path.toAbsolutePath(), il vérifie si la longueur du chemin est supérieure à zéro, sinon il utilise la user.dirpropriété système et renvoie le chemin actuel.

Voici le code pour l'implémentation du système de fichiers Unix: UnixPath.toAbsolutePath ()


En gros, vous devez créer à Pathnouveau l' instance une fois que vous avez résolu le chemin du répertoire actuel.

Je suggérerais également d'utiliser File.separatorCharpour le code indépendant de la plate-forme.

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

Production:

/Users/user/coding/data/foo.txt
JeuneHobbit
la source
Pas moi, peut-être que quelqu'un pense travailler sur des cordes et separatorCharest inférieur à une "abstraction de niveau supérieur", quelque chose qui ressemble àPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575
22

Paths#get(String first, String... more) États,

Convertit une chaîne de chemin, ou une séquence de chaînes qui, une fois jointes, forment une chaîne de chemin, en un fichier Path.

...

Un Pathreprésentant un chemin vide est retourné si first est la chaîne vide et que plus ne contient aucune chaîne non vide.

Pour obtenir le répertoire actuel des utilisateurs, vous pouvez simplement utiliser System.getProperty("user.dir").

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

De plus, la getméthode utilise l' argument de longueur variable de String, qui sera utilisé pour fournir les chaînes de chemin suivantes. Donc, pour créer Pathpour /test/inside/abc.txtvous devez l'utiliser de la manière suivante,

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

Pas une méthode spécifique.

Si vous utilisez java 8 ou supérieur, vous avez 2 options:

a) Utilisez java.util.StringJoiner

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

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

Si vous utilisez java 7 ou une version antérieure, vous pouvez utiliser la bibliothèque commons-lang d'apache commons. La classe StringUtils a une méthode pour joindre des chaînes à l'aide d'un séparateur.

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

Remarque: vous pouvez utiliser le séparateur de chemin linux "/" pour Windows (rappelez-vous simplement que les chemins absolus sont quelque chose comme "/ C: / mydir1 / mydir2". Utiliser always "/" est très utile si vous utilisez des protocoles tels que file: //

Rober2D2
la source
StringJoiner m'a retourné/home/user/test:foo.txt
cybertextron
Les options que vous connaissez ne sont pas les seules existantes. On pourrait utiliser StringBuilder au lieu de joiner, par exemple. Et en fait, votre implémentation basée sur des chaînes plutôt que sur des fichiers / chemins est assez naïve et entraînerait des problèmes dans de nombreux scénarios.
XenoRo
2
File.separatora travaillé pour moi au lieu deFile.pathSeparator
Evan Siroky
utilisez Pathes.get ("path1", "path2"). toAbsolutePath (). toString ()
Erdinc Ay
6

Le moyen le plus simple est:

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

Vous ne devriez jamais écrire Paths.get(""). Je suis surpris que cela fonctionne du tout. Si vous souhaitez faire référence explicitement au répertoire actuel, utilisez Paths.get(System.getProperty("user.dir")). Si vous voulez le répertoire personnel de l'utilisateur, utilisez Paths.get(System.getProperty("user.home")).

Vous pouvez également combiner les approches:

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

Le moyen le plus fiable et indépendant de la plate-forme de joindre des chemins en Java consiste à utiliser Path::resolve(comme indiqué dans JavaDoc pour Paths::get). Pour un tableau de longueur arbitraire de chaînes représentant des morceaux d'un chemin, celles-ci peuvent être jointes à l'aide d'un flux 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);
}
Patrick Parker
la source
1

Tu peux faire comme

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

Un bon article détaillé est ici Path Sample Usecase

Robin Mathur
la source