Создать символическую ссылку с Java

1. обзор

В этом руководстве мы рассмотрим различные способы создания символической ссылки в Java с использованиемNIO.2 API, а также изучим различия между жесткими и программными ссылками на файлы.

Во-первых, давайте определим, что такое файловые ссылки и каково их ожидаемое поведение. A file link is a pointer that transparently references a file stored in the file system.

Распространенное заблуждение - думать, что ссылка на файл - это ярлык, поэтому давайте проверим их поведение:

  • Ярлык - это обычный файл, который ссылается на целевой файл

  • Soft/Symbolic link is a file pointer that behaves as the file that is linking to – if the target file gets deleted then the link is unusable

  • Жесткая ссылка - это указатель файла, который отражает файл, на который он ссылается, поэтому в основном это похоже на клон. Если целевой файл удаляется, файл ссылки по-прежнему действителен

Большинство операционных систем (Linux, Windows, Mac) уже поддерживают программные / жесткие ссылки на файлы, поэтому работать над ними с помощьюNIO API не должно быть проблемой.

Во-первых, мы должны создать целевой файл для ссылки, поэтому давайте упорядочим некоторые данные в файл:

public Path createTextFile() throws IOException {
    byte[] content = IntStream.range(0, 10000)
      .mapToObj(i -> i + System.lineSeparator())
      .reduce("", String::concat)
      .getBytes(StandardCharsets.UTF_8);
    Path filePath = Paths.get("", "target_link.txt");
    Files.write(filePath, content, CREATE, TRUNCATE_EXISTING);
    return filePath;
}

Давайте создадим символическую ссылку на существующий файл, убедившись, что созданный файл является символической ссылкой:

public void createSymbolicLink() throws IOException {
    Path target = createTextFile();
    Path link = Paths.get(".","symbolic_link.txt");
    if (Files.exists(link)) {
        Files.delete(link);
    }
    Files.createSymbolicLink(link, target);
}

Затем давайте посмотрим на создание жесткой ссылки:

public void createHardLink() throws IOException {
    Path target = createTextFile();
    Path link = Paths.get(".", "hard_link.txt");
    if (Files.exists(link)) {
        Files.delete(link);
    }
    Files.createLink(link, target);
}

Перечисляя файлы с их различиями, мы видим, что размер файла мягкой / символьной ссылки невелик, тогда как жесткая ссылка использует то же пространство, что и связанный файл:

 48K  target_link.txt
 48K    hard_link.txt
4.0K    symbolic_link.txt

Чтобы четко понять, какие исключения могут возникать, давайте посмотрим на отмеченные исключения для операций:

  • UnsupportedOperationException - когда JVM не поддерживает ссылки на файлы в определенной системе

  • FileAlreadyExistsException - когда файл ссылки уже существует, переопределение не поддерживается по умолчанию

  • IOException - при возникновении ошибки ввода-вывода, например неверный путь к файлу

  • SecurityException - когда файл ссылки не может быть создан или целевой файл недоступен из-за ограниченных прав доступа к файлу

Теперь, если у нас есть данная файловая система с существующими ссылками на файлы, их можно идентифицировать и отображать целевые файлы:

public void printLinkFiles(Path path) throws IOException {
    try (DirectoryStream stream = Files.newDirectoryStream(path)) {
        for (Path file : stream) {
            if (Files.isDirectory(file)) {
                printLinkFiles(file);
            } else if (Files.isSymbolicLink(file)) {
                System.out.format("File link '%s' with target '%s' %n",
                  file, Files.readSymbolicLink(file));
            }
        }
    }
}

Если мы выполним это в нашем текущем пути:

printLinkFiles(Paths.get("."));

Мы получили бы вывод:

File link 'symbolic_link.txt' with target 'target_link.txt'

Note that hard link files aren’t simply identifiable with NIO’s API,low-level operations необходимы для работы с такими файлами.

5. Заключение

В этой статье описывается различный тип ссылок на файлы, их различие с ярлыками, а также способы их создания и управления ими с использованием чистого Java API, который работает с основными файловыми системами на рынке.

Реализацию этих примеров и фрагментов кода можно найти вover on GitHub.