在Java中joinpath

Python我可以使用os.path.joinjoin两条path:

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

我试图在Java中实现相同的function,而不用担心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( )将join我的当前目录/home/user/testdata/foo.txt使/home/user/test/data/foo.txt 。 我错了什么?

尽pipe使用empty String获取当前目录的原始解决scheme起作用。 但是build议使用当前目录的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类文档:

如果path仅由一个empty名称元素组成,则该path被认为是空path。 使用empty path is equivalent to accessing the default directory访问文件empty path is equivalent to accessing the default directory文件系统empty path is equivalent to accessing the default directory


为什么Paths.get("").toAbsolutePath()作品

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

这里是Unix文件系统实现的代码: UnixPath.toAbsolutePath()


基本上,您需要在parsing当前目录path后再次创buildPath实例。

此外,我会build议使用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)表示,

将pathstring或连接时形成pathstring的string序列转换为path。

如果首先是空string,并且不包含任何非空string,则返回表示path的path。

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

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

此外, get方法使用String 可变长度参数 ,它将用于提供后续的pathstring。 因此,要为/test/inside/abc.txt创buildPath ,您必须按以下方式使用它,

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

不是一个具体的方法。

如果你使用java 8或更好,你有2个选项:

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

如果您使用java 7或更低版​​本,则可以使用来自apache commons的commons-lang库。 StringUtils类有一个使用分隔符连接string的方法。

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

注意:你可以使用linux的pathseparator“/”作为windows(只要记住绝对path是类似于“/ 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中joinpath的最可靠,独立于平台的方法是使用Path::resolve (如JavaDoc for Paths::get )。 对于表示path片断的任意长度的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); }