Unindo caminhos em Java


99

Em Pythonposso unir dois caminhos com os.path.join:

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

Estou tentando conseguir o mesmo em Java, sem me preocupar se o OSé 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);

}

Eu esperava que isso Path.resolve( )se juntaria ao meu diretório atual /home/user/testcom o data/foo.txtmaking /home/user/test/data/foo.txt. O que estou entendendo de errado?


1
isso pode ser algo que não estou vendo. Seu caminho atual é "". Seu segundo caminho é "data / foo.txt". Talvez o seu problema seja que você parece estar imprimindo um objeto Path em vez defilepath.toString()
cjds

2
Usonew File(parent, child)
saka1029

Respostas:


99

Mesmo que a solução original para obter o diretório atual usando as empty Stringobras. Mas é recomendado usar a user.dirpropriedade para o diretório atual e user.homepara o diretório inicial.

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

resultado:

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

Da documentação da classe Java Path :

Um caminho é considerado um caminho vazio se consistir apenas em um elemento de nome, ou seja empty. Acessando um arquivo usando um empty path is equivalent to accessing the default directorydo sistema de arquivos.


Porque Paths.get("").toAbsolutePath()funciona

Quando uma string vazia é passada para o Paths.get(""), o Pathobjeto retornado contém o caminho vazio. Mas quando chamamos Path.toAbsolutePath(), ele verifica se o comprimento do caminho é maior que zero, caso contrário, ele usa a user.dirpropriedade do sistema e retorna o caminho atual.

Aqui está o código para a implementação do sistema de arquivos Unix: UnixPath.toAbsolutePath ()


Basicamente, você precisa criar a Pathinstância novamente depois de resolver o caminho do diretório atual.

Também gostaria de sugerir o uso File.separatorCharde código independente de 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);

Resultado:

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

Não eu, talvez alguém pense em trabalhar com cordas e separatorCharseja inferior a alguma "abstração de nível superior", algo que se parece comPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575

22

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

Converte uma string de caminho, ou uma sequência de strings que, quando unidas, formam uma string de caminho em um Path.

...

Um Pathrepresentando um caminho vazio é retornado se primeiro for a string vazia e more não contiver nenhuma string não vazia.

Para obter o diretório do usuário atual, você pode simplesmente usar System.getProperty("user.dir").

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

Além disso, o getmétodo usa o argumento de comprimento variável de String, que será usado para fornecer strings de caminho subsequentes. Então, para criar Pathpara /test/inside/abc.txtvocê tem que usá-lo da seguinte maneira,

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

11

Não é um método específico.

Se você usa java 8 ou melhor, tem 2 opções:

a) Use java.util.StringJoiner

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

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

Se você usa java 7 ou inferior, pode usar a biblioteca commons-lang do apache commons. A classe StringUtils tem um método para unir strings usando um separador.

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

Uma nota: você pode usar linux pathseparator "/" para windows (lembre-se de que caminhos absolutos são algo como "/ C: / mydir1 / mydir2". Usar sempre "/" é muito útil se você usar protocolos como file: //


StringJoiner me devolveu/home/user/test:foo.txt
cybertextron

As opções que você conhece não são as únicas que existem. Pode-se usar StringBuilder em vez de joiner, por exemplo. E, de fato, sua implementação baseada em Strings em vez de arquivos / caminhos é bastante ingênua e pode causar problemas em muitos cenários.
XenoRo

2
File.separatortrabalhou para mim em vez deFile.pathSeparator
Evan Siroky

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

5

A maneira mais básica é:

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

Você nunca deve escrever Paths.get(""). Estou surpreso que funcione. Se você quiser se referir ao diretório atual explicitamente, use Paths.get(System.getProperty("user.dir")). Se quiser o diretório inicial do usuário, use Paths.get(System.getProperty("user.home")).

Você também pode combinar as abordagens:

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

1

A maneira mais confiável e independente de plataforma de unir caminhos em Java é usando Path::resolve(conforme observado no JavaDoc para Paths::get). Para uma matriz de comprimento arbitrário de Strings representando partes de um caminho, eles podem ser unidos usando um 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

Você pode fazer como

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

Um bom post detalhado está aqui. Path Sample Usecase

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.