Unir caminos en Java

99

En Pythonpuedo unir dos caminos con os.path.join:

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

Estoy tratando de achive la misma en Java, sin preocuparse de si la OSes 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);

}

Esperaba que Path.resolve( )se uniera a mi directorio actual /home/user/testcon data/foo.txtmaking /home/user/test/data/foo.txt. ¿Qué me estoy equivocando?

cibertextrón
fuente
1
esto podría ser algo que no estoy viendo. Su ruta actual es "". Su segunda ruta es "data / foo.txt". Tal vez su problema es que parece estar imprimiendo un objeto Path en lugar defilepath.toString()
cjds
2
Usonew File(parent, child)
saka1029

Respuestas:

99

Aunque la solución original para obtener el directorio actual usando empty Stringworks. Pero se recomienda utilizar la user.dirpropiedad para el directorio actual y user.homepara el directorio de inicio.

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

salida:

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

De la documentación de la clase Java Path :

Una ruta se considera una ruta vacía si consta únicamente de un elemento de nombre que es empty. Accediendo a un archivo usando un empty path is equivalent to accessing the default directorysistema de archivos.


Por que Paths.get("").toAbsolutePath()funciona

Cuando se pasa una cadena vacía al Paths.get(""), el Pathobjeto devuelto contiene una ruta vacía. Pero cuando llamamos Path.toAbsolutePath(), verifica si la longitud de la ruta es mayor que cero; de lo contrario, usa la user.dirpropiedad del sistema y devuelve la ruta actual.

Aquí está el código para la implementación del sistema de archivos Unix: UnixPath.toAbsolutePath ()


Básicamente, debe crear la Pathinstancia nuevamente una vez que resuelva la ruta del directorio actual.

También sugeriría usar File.separatorCharcódigo independiente de la plataforma.

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

Salida:

/Users/user/coding/data/foo.txt
JovenHobbit
fuente
Yo no, tal vez alguien piense que trabajar en cadenas y separatorChares inferior a alguna "abstracción de nivel superior", algo que se parece aPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575
22

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

Convierte una cadena de ruta, o una secuencia de cadenas que cuando se unen forman una cadena de ruta, en un Path.

...

Se devuelve Pathuna representación de una ruta vacía si primero es la cadena vacía y más no contiene ninguna cadena no vacía.

Para obtener el directorio de usuarios actual, simplemente puede usar System.getProperty("user.dir").

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

Además, el getmétodo utiliza el argumento de longitud variable de String, que se utilizará para proporcionar cadenas de ruta posteriores. Por lo tanto, para crear Pathpor /test/inside/abc.txtlo que tienes que usarlo de una manera siguiente,

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

No es un método específico.

Si usa java 8 o mejor, tiene 2 opciones:

a) Utilice java.util.StringJoiner

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

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

Si usa java 7 o versiones anteriores, puede usar la biblioteca commons-lang de apache commons. La clase StringUtils tiene un método para unir cadenas usando un separador.

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

Una nota al margen: puede usar el separador de rutas de Linux "/" para Windows (solo recuerde que las rutas absolutas son algo como "/ C: / mydir1 / mydir2". Usar siempre "/" es muy útil si usa protocolos como file: //

Rober2D2
fuente
StringJoiner me devolvió/home/user/test:foo.txt
cybertextron
Las opciones que conoce no son las únicas que existen. Se podría utilizar StringBuilder en lugar de joiner, por ejemplo. Y de hecho, su implementación basada en cadenas en lugar de archivos / rutas es bastante ingenua y generaría problemas en muchos escenarios.
XenoRo
2
File.separatortrabajó para mí en lugar deFile.pathSeparator
Evan Siroky
use Pathes.get ("ruta1", "ruta2"). toAbsolutePath (). toString ()
Erdinc Ay
5

La forma más básica es:

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

Nunca deberías escribir Paths.get(""). Me sorprende que funcione en absoluto. Si desea hacer referencia al directorio actual de forma explícita, utilice Paths.get(System.getProperty("user.dir")). Si desea el directorio de inicio del usuario, use Paths.get(System.getProperty("user.home")).

También puede combinar los enfoques:

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

La forma más confiable e independiente de la plataforma de unir rutas en Java es usando Path::resolve(como se indica en JavaDoc para Paths::get). Para una matriz de cadenas de longitud arbitraria que representan partes de una ruta, estas se pueden unir utilizando una secuencia de 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
fuente
1

Puedes hacer como

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

Una buena publicación detallada está aquí .

Robin Mathur
fuente