Не существует встроенного средства для создания FileSystem
с chroot
подобной семантикой. Файловая система по умолчанию поддерживает только file:///
в качестве URI и не допускает более одного экземпляра.
В этом отношении FileSystems.getDefault().getPath("test.file")
создает относительный путь, как и Paths.get("test.file")
. Разница между относительными путями, созданными для файловой системы по умолчанию и других файловых систем, заключается в поведении разрешения, когда не указан другой базовый путь (например, при вызове toAbsolutePath()
или просто при попытке открыть их). Но разрешение по текущему рабочему каталогу не делает их корневым путем.
Лучшее решение для реализации операций, не связанных с файловой системой, - позволить коду получить базовые Path
объекты, чтобы разрешить относительные пути к.
например. простая подпрограмма копирования дерева может выглядеть так:
static void copyTree(Path sourceBase, Path targetBase) throws IOException {
try {
Files.walk(sourceBase).forEach(path -> {
if(Files.isRegularFile(path)) try {
Path target = targetBase.resolve(sourceBase.relativize(path).toString());
if(!Files.isDirectory(target.getParent()))
Files.createDirectories(target.getParent());
Files.copy(path, target, StandardCopyOption.COPY_ATTRIBUTES);
} catch(IOException ex) {
throw new UncheckedIOException(ex);
}
});
} catch(UncheckedIOException ex) {
throw ex.getCause();
}
}
Для этого метода не имеет значения, копируете ли вы из каталога с жестким диском в другой каталог с жестким диском или в файловую систему zip, или из файловой системы zip в жесткий диск, или из zip-файла в другой zip-файл, и т.д.
Наиболее интересная часть - это вызов sourceBase.relativize(path)
, чтобы получить относительный путь от исходного базового пути к подпутьу фактического файла. Поскольку относительные Path
экземпляры по-прежнему связаны с определенной файловой системой, код вызывает toString()
, прежде чем передать его в targetBase.resolve(…)
, чтобы убедиться, что он будет работать в разных файловых системах. Обратите внимание, что path.resolve(string)
эквивалентно path.resolve(path.getFileSystem().getPath(string))
. Было бы законно, если бы метод сначала проверял, принадлежат ли оба экземпляра Path
к одной и той же файловой системе, в этом случае пропустить обход String
.