Java 生成规范路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2683676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generating a canonical path
提问by Joel
Does any one know of any Java libraries I could use to generate canonical paths (basically remove back-references).
有谁知道我可以用来生成规范路径的任何 Java 库(基本上删除反向引用)。
I need something that will do the following:
我需要一些可以执行以下操作的东西:
Raw Path -> Canonical Path
原始路径 -> 规范路径
/../foo/ -> /foo
/foo/ -> /foo
/../../../ -> /
/./foo/./ -> /foo
//foo//bar -> /foo/bar
//foo/../bar -> /bar
etc...
等等...
At the moment I lazily rely on using:
目前我懒洋洋地依赖于使用:
new File("/", path).getCanonicalPath();
But this resolves the path against the actual file system, and is synchronised.
但这会根据实际文件系统解析路径,并进行同步。
java.lang.Thread.State: BLOCKED (on object monitor)
at java.io.ExpiringCache.get(ExpiringCache.java:55)
- waiting to lock <0x93a0d180> (a java.io.ExpiringCache)
at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:137)
at java.io.File.getCanonicalPath(File.java:559)
The paths that I am canonicalising do not exist on my file system, so just the logic of the method will do me fine, thus not requiring any synchronisation. I'm hoping for a well tested library rather than having to write my own.
我规范化的路径在我的文件系统中不存在,所以只要方法的逻辑就可以了,因此不需要任何同步。我希望有一个经过良好测试的库,而不必自己编写。
采纳答案by Stephen C
I think you can use the URIclass to do this; e.g. if the path contains no characters that need escaping in a URI path component, you can do this.
我认为你可以使用URI类来做到这一点;例如,如果路径不包含需要在 URI 路径组件中转义的字符,您可以这样做。
String normalized = new URI(path).normalize().getPath();
If the path contains (or might contain) characters that need escaping, the multi-argument constructors will escape the path
argument, and you can provide null
for the other arguments.
如果路径包含(或可能包含)需要转义的字符,多参数构造函数将转义path
参数,您可以提供null
其他参数。
Notes:
笔记:
The above normalizes a file path by treating it as a relative URI. If you want to normalize an entire URI ... including the (optional) scheme, authority, and other components, don't call
getPath()
!URI normalization does not involve looking at the file system as File canonicalization does. But the flip side is that normalization behaves differently to canonicalization when there are symbolic links in the path.
以上通过将文件路径视为相对 URI 来规范化文件路径。如果您想规范化整个 URI ... 包括(可选)方案、权限和其他组件,请不要调用
getPath()
!URI 规范化不像文件规范化那样涉及查看文件系统。但另一方面,当路径中有符号链接时,规范化与规范化的行为不同。
回答by Haldean Brown
You could try an algorithm like this:
你可以试试这样的算法:
String collapsePath(String path) {
/* Split into directory parts */
String[] directories = path.split("/");
String[] newDirectories = new String[directories.length];
int i, j = 0;
for (i=0; i<directories.length; i++) {
/* Ignore the previous directory if it is a double dot */
if (directories[i].equals("..") && j > 0)
newDirectories[j--] = "";
/* Completely ignore single dots */
else if (! directories[i].equals("."))
newDirectories[j++] = directories[i];
}
/* Ah, what I would give for String.join() */
String newPath = new String();
for (i=0; i < j; i++)
newPath = newPath + "/" + newDirectories[i];
return newPath;
}
It isn't perfect; it's linear over the number of directories but does make a copy in memory.
它并不完美;它与目录数量呈线性关系,但会在内存中进行复制。
回答by tom91136
Using Apache Commons IO(a well-known and well-tested library)
使用Apache Commons IO(一个众所周知且经过充分测试的库)
public static String normalize(String filename)
will do exactly what you're looking for.
会做你正在寻找的。
Example:
例子:
String result = FilenameUtils.normalize(myFile.getAbsolutePath());
回答by Roland
Which kind of path is qualified as a Canonical Path is OS dependent. That's why Java need to check it on the filesystem. So there's no simple logic to test the path without knowing the OS.
哪种路径符合规范路径取决于操作系统。这就是 Java 需要在文件系统上检查它的原因。因此,在不了解操作系统的情况下没有简单的逻辑来测试路径。
回答by Andrej Golcov
If you don't need path canonization but only normalization, in Java 7 you can use java.nio.file.Path.normalize
method.
According to http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html:
如果您不需要路径规范化而只需要规范化,则在 Java 7 中您可以使用java.nio.file.Path.normalize
method。根据http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html:
This method does not access the file system; the path may not locate a file that exists.
该方法不访问文件系统;路径可能找不到存在的文件。
If you work with File object you can use something like this:
如果您使用 File 对象,您可以使用以下内容:
file.toPath().normalize().toFile()
回答by dlamblin
I'm assuming you have strings and you want strings, and you have Java 7 available now, and your default file system uses '/' as a path separator, so try:
我假设您有字符串并且想要字符串,并且您现在有 Java 7,并且您的默认文件系统使用“/”作为路径分隔符,因此请尝试:
String output = FileSystems.getDefault().getPath(input).normalize().toString();
You can try this out with:
你可以试试这个:
/**
* Input Output
* /../foo/ -> /foo
* /foo/ -> /foo
* /../../../ -> /
* /./foo/./ -> /foo
* //foo//bar -> /foo/bar
* //foo/../bar -> /bar
*/
@Test
public void testNormalizedPath() throws URISyntaxException, IOException {
String[] in = new String[]{"/../foo/", "/foo/", "/../../../", "/./foo/./",
"//foo/bar", "//foo/../bar", "/", "/foo"};
String[] ex = new String[]{"/foo", "/foo", "/", "/foo", "/foo/bar", "/bar", "/", "/foo"};
FileSystem fs = FileSystems.getDefault();
for (int i = 0; i < in.length; i++) {
assertEquals(ex[i], fs.getPath(in[i]).normalize().toString());
}
}
回答by JonAar Livernois
So, while normalizing can do the trick, here is a procedure that exposes a little more of the Java API than would simply calling Paths.normalize()
因此,虽然规范化可以解决问题,但这里有一个过程,它比简单地调用更多的 Java API Paths.normalize()
Say I want to find a file that is not in my current directory on the file system. My working code file is
假设我想在文件系统上找到一个不在我当前目录中的文件。我的工作代码文件是
myproject/src/JavaCode.java
myproject/src/JavaCode.java
Located in myproject/src/. My file is in
位于 myproject/src/。我的文件在
../../data/myfile.txt
../../data/myfile.txt
I'm testing my program running my code from JavaCode.java
我正在测试从 JavaCode.java 运行我的代码的程序
public static void main(String[] args) {
findFile("../../data","myfile.txt");
System.out.println("Found it.");
}
public static File findFile(String inputPath, String inputFile) {
File dataDir = new File("").getAbsoluteFile(); // points dataDir to working directory
String delimiters = "" + '\' + '/'; // dealing with different system separators
StringTokenizer st = new StringTokenizer(inputPath, delimiters);
while(st.hasMoreTokens()) {
String s = st.nextToken();
if(s.trim().isEmpty() || s.equals("."))
continue;
else if(s.equals(".."))
dataDir = dataDir.getParentFile();
else {
dataDir = new File(dataDir, s);
if(!dataDir.exists())
throw new RuntimeException("Data folder does not exist.");
}
}
return new File(dataDir, inputFile);
}
Having placed a file at the specified location, this should print "Found it."
将文件放置在指定位置后,应该打印“找到它”。