2009-01-05 26 views
245

¿Hay un equivalente Java para System.IO.Path.Combine() en C# /. NET? O cualquier código para lograr esto?¿Cómo combinar rutas en Java?

Este método estático combina una o más cadenas en una ruta.

+0

[Este] (http://stackoverflow.com/questions/204784/ how-to-construct-a-relative-path-in-java-from-two-absolute-paths-or-urls) La pregunta SO podría ayudar. –

Respuesta

315

En lugar de mantener todo basado en cadenas, debe usar una clase que esté diseñada para representar una ruta del sistema de archivos.

Si está utilizando Java 7 o Java 8, debería considerar utilizar java.nio.file.Path; Path.resolve se puede usar para combinar una ruta con otra o con una cadena. La clase de ayuda Paths también es útil. Por ejemplo:

Path path = Paths.get("foo", "bar", "baz.txt"); 

Si tiene que atender a los pre Java-7-ambientes, puede utilizar java.io.File, así:

File baseDirectory = new File("foo"); 
File subDirectory = new File(baseDirectory, "bar"); 
File fileInDirectory = new File(subDirectory, "baz.txt"); 

Si quieres de vuelta como una cadena posterior, puede llame al getPath(). De hecho, si realmente quería imitar Path.Combine, usted podría escribir algo como:

public static String combine(String path1, String path2) 
{ 
    File file1 = new File(path1); 
    File file2 = new File(file1, path2); 
    return file2.getPath(); 
} 
+7

Cuidado con los caminos absolutos. La versión .NET devolverá 'path2' (ignorando' path1') si 'path2' es una ruta absoluta. La versión de Java soltará el '/' o '\' y lo tratará como una ruta relativa. – finnw

+6

¿Por qué java usa 'File' para directorios, en lugar de una clase' Directory' separada? –

+0

@Matthew: No estoy seguro, para ser honesto ... –

37

La respuesta principal es el uso de objetos de archivo. Sin embargo, Commons IO tiene una clase FilenameUtils que puede hacer este tipo de cosas, como el método concat().

+8

+1 por no reinventar lo que ya se hace perfectamente en las bibliotecas de Apache commons – alpian

+7

FilenameUtils.concat, para ser precisos. http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FilenameUtils.html#concat%28java.lang.String,%20java.lang.String%29 – MikeFHay

+0

Si trabajas con algo como JSF, definitivamente quieres mantenerlo basado en cadenas ya que todos los caminos que obtendrás estarán basados ​​en cadenas. – DanielK

10

Para mejorar la respuesta de JodaStephen, Apache Commons IO tiene FilenameUtils que hace esto. Ejemplo (en Linux):

assert org.apache.commons.io.FilenameUtils.concat("/home/bob", "work\\stuff.log") == "/home/bob/work/stuff.log" 

Es independiente de la plataforma y producirá los separadores que su sistema necesite.

0

He aquí una solución que maneja varias partes de trayectoria y condiciones de borde:

public static String combinePaths(String ... paths) 
{ 
    if (paths.length == 0) 
    { 
    return ""; 
    } 

    File combined = new File(paths[0]); 

    int i = 1; 
    while (i < paths.length) 
    { 
    combined = new File(combined, paths[i]); 
    ++i; 
    } 

    return combined.getPath(); 
} 
12

Sé que es un largo tiempo desde respuesta original de Jon, pero tenía un requisito similar al OP.

Al extender la solución de Jon, se me ocurrió lo siguiente, que tomará uno o más segmentos de ruta para tomar tantos segmentos de camino que pueda lanzar.

Uso

Path.combine("/Users/beardtwizzle/"); 
Path.combine("/", "Users", "beardtwizzle"); 
Path.combine(new String[] { "/", "Users", "beardtwizzle", "arrayUsage" }); 

Código aquí por otros con un problema similar

public class Path { 
    public static String combine(String... paths) 
    { 
     File file = new File(paths[0]); 

     for (int i = 1; i < paths.length ; i++) { 
      file = new File(file, paths[i]); 
     } 

     return file.getPath(); 
    } 
} 
48

En Java 7, se debe utilizar resolve:

Path newPath = path.resolve(childPath); 

Mientras que el NIO2 Palmadita La clase h puede parecer un poco redundante para File con una API innecesariamente diferente, de hecho es sutilmente más elegante y robusta.

Tenga en cuenta que Paths.get() (como se sugiere por otra persona) no tiene una sobrecarga de tomar una Path, y haciendo Paths.get(path.toString(), childPath) NO es lo mismo que resolve().resolve() es más inteligente. Desde el Paths.get() docs:

Nótese que si bien este método es muy conveniente, utilizando implicará una referencia supone que el sistema de archivos por defecto y limitar la utilidad del código de llamada. Por lo tanto, no debe utilizarse en el código de la biblioteca destinado a la reutilización flexible. Una alternativa más flexible es utilizar una instancia de trazado existentes como ancla, como por ejemplo:

Path dir = ... 
Path path = dir.resolve("file"); 

La función hermana para resolve es el excelente relativize:

Path childPath = path.relativize(newPath); 
0

Si no necesita más que las cuerdas, puede utilizar com.google.common.io.Files

Files.simplifyPath("some/prefix/with//extra///slashes" + "file//name") 

para obtener

"some/prefix/with/extra/slashes/file/name" 
3

plataforma de enfoque independiente (File.separator utiliza, es decir, lo hará obras depende de sistema de operación en código se ejecuta:

java.nio.file.Paths.get(".", "path", "to", "file.txt") 
// relative unix path: ./path/to/file.txt 
// relative windows path: .\path\to\filee.txt 

java.nio.file.Paths.get("/", "path", "to", "file.txt") 
// absolute unix path: /path/to/filee.txt 
// windows network drive path: \\path\to\file.txt 

java.nio.file.Paths.get("C:", "path", "to", "file.txt") 
// absolute windows path: C:\path\to\file.txt