在 Java 中连接路径

Python中,我可以用 os.path.join连接两条路径:

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

我试图在 Java 中达到同样的效果,而不用担心 OSUnixSolaris还是 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);


}

我原以为 Path.resolve( )会加入我的工作目录 /home/user/testdata/foo.txt一起制作 /home/user/test/data/foo.txt。 我哪里搞错了?

116035 次浏览

虽然使用 abc0获得工作目录的原始解决方案是可行的。但建议对工作目录使用 user.dir属性,对主目录使用 user.home属性。

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

产出:

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

来自 Java路径类文档:

如果 Path 仅由一个名称元素 empty组成,则将其视为空路径。使用文件系统的 empty path is equivalent to accessing the default directory访问文件。


为什么 Paths.get("").toAbsolutePath()会起作用

当一个空字符串传递给 Paths.get("")时,返回的 Path对象包含空路径。但是当我们调用 Path.toAbsolutePath()时,它检查路径长度是否大于零,否则它使用 user.dir系统属性并返回当前路径。

下面是 Unix文件系统实现的代码:


基本上,一旦解析了工作目录路径,就需要再次创建 Path实例。

我还建议使用 File.separatorChar编写独立于平台的代码。

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

产出:

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

Paths#get(String first, String... more) 状态,

将一个路径字符串,或者当以路径字符串形式连接时的 字符串序列字符串序列转换为 Path

...

如果 first 为空,则返回表示 空荡荡的路径的 Path String 和 more 不包含任何非空字符串。

要获得当前的用户目录,只需使用 System.getProperty("user.dir")

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

而且,get方法使用 String可变长度参数,它将用于提供后续的路径字符串。因此,要为 /test/inside/abc.txt创建 Path,您必须以下面的方式使用它,

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

不是特定的方法。

如果你使用 java 8或更好,你有两个选择:

A)使用 java.util. StringJoiner

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

B)使用 String.join(File.pathSeparator, "path1", "path2");

如果使用 java7或更低版本,则可以使用来自 apachecommons 的 commons-lang 库。StringUtils 类有一个使用分隔符连接字符串的方法。

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

旁注: 您可以使用 linux 路径分隔符“/”作为窗口(只要记住绝对路径类似于“/C:/mydir1/mydir2”)。如果您使用诸如 file://之类的协议,那么始终使用“/”非常有用

最基本的方法是:

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

你永远不应该写 Paths.get("")。我很惊讶这居然有用。如果要明确引用工作目录,请使用 Paths.get(System.getProperty("user.dir"))。如果需要用户的主目录,请使用 Paths.get(System.getProperty("user.home"))

你也可以把这些方法结合起来:

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

在 Java 中,连接路径最可靠、独立于平台的方法是使用 Path::resolve(正如 JavaDoc for Paths::get中所指出的)。对于表示路径片段的任意长度的 String 数组,可以使用 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);
}

你可以这么做

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

一个很好的详细的职位是在这里 路径示例用例

对于 Java > = 11,现在推荐的方法是使用 路径而不是 小径,走,正如前面的答案所建议的那样。引用 Java11医生:

建议通过 Path.of 方法获取 Path,而不是通过这个类中定义的 get 方法获取,因为这个类在将来的版本中可能会被弃用。

例如,根据操作系统的路径分隔符,下面将加入“ foo”和“ bar”:

import java.nio.file.Path;
...


Path fooBar = Path.of("foo", "bar");