Предположим, у меня есть следующие объекты java.io.File
и соответствующие объекты java.nio.file.Path
:
final String windir = "WINNT";
final String comspec = "cmd.exe";
final File absoluteFile = new File(format("C:\\./foo/../bar/../%s/./././././SYSTEM32/../system/../System32/%s", windir, comspec)).getAbsoluteFile();
final Path absolutePath = absoluteFile.toPath();
Теперь я хочу определить канонический путь, т.е. е. удалите все записи пути .
или ..
, чтобы результирующий путь был C:\WINNT\System32\cmd.exe
.
java.io.File.getCanonicalPath()
подходит, за исключением того, что он следует символическим ссылкам на Unices, которых я хотел бы избежать.
java.nio.file.Path.toRealPath(NOFOLLOW_LINKS)
, с другой стороны, возвращает канонический путь без перехода по символическим ссылкам, но выдает ошибку java.nio.file.NoSuchFileException
.
Как определить канонический путь к файлу
- безопасным способом (чтобы не возникало исключений в случае, если файл не существует),
- независимо от платформы и
- без перехода по символическим ссылкам?
Единственное решение, которое я нашел до сих пор, — это вернуться к старому java.io
API:
@NonNull Path toCanonicalPath(final @NonNull Path path) throws IOException {
try {
/*
* Fails for nonexistent files.
*/
return path.toRealPath(NOFOLLOW_LINKS);
} catch (final NoSuchFileException ignored) {
/*
* This one is fine except it always follows symbolic links on Unices.
*/
return path.toFile().getCanonicalFile().toPath();
} catch (final FileSystemException ignored) {
/*
* Thrown when there's a file/directory conflict, e. g.
* for a non-existent file "foo/bar", "foo" already
* exists and is a symlink, not a directory. In this
* case, we can't use the File#getCanonicalFile() call.
*/
return path.toAbsolutePath();
}
}
Есть ли менее уродливый подход?
.
или..
, т.е. е. Мне нужен кратчайший абсолютный путь (но без разрешения символической ссылки). - person Bass   schedule 29.08.2017