Criar um link simbólico com Java

1. Visão geral

Neste tutorial, vamos explorar diferentes maneiras de criar um link simbólico em Java usandoNIO.2 API, e explorar as diferenças entre links de arquivos físicos e virtuais.

Primeiro, vamos definir o que são links de arquivo e qual é o comportamento esperado. A file link is a pointer that transparently references a file stored in the file system.

Um mal-entendido comum é pensar que um link de arquivo é um atalho, então vamos verificar seu comportamento:

  • Um atalho é um arquivo regular que faz referência a um arquivo de destino

  • 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

  • Um hard link é um ponteiro de arquivo que espelha o arquivo ao qual está vinculado, então é basicamente como um clone. Se o arquivo de destino for excluído, o arquivo de link ainda será válido

A maioria dos sistemas operacionais (Linux, Windows, Mac) já oferece suporte a links de arquivos virtuais / físicos, então não deve ser um problema trabalhar neles usandoNIO API.

Primeiro, temos que criar um arquivo de destino para vincular, então vamos sequenciar alguns dados em um arquivo:

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;
}

Vamos criar um link simbólico para um arquivo existente, garantindo que o arquivo criado seja um link simbólico:

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

A seguir, vamos dar uma olhada na criação de um hard link:

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

Ao listar os arquivos com suas diferenças, podemos ver que o tamanho do arquivo de link simbólico / flexível é pequeno, enquanto o link físico está usando o mesmo espaço que o arquivo vinculado:

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

Para entender claramente quais são as possíveis exceções que podem ser lançadas, vamos ver as exceções verificadas nas operações:

  • UnsupportedOperationException - quando a JVM não suporta links de arquivo em um sistema específico

  • FileAlreadyExistsException - quando o arquivo de link já existe, a substituição não é suportada por padrão

  • IOException - quando ocorre um erro IO, por exemplo caminho de arquivo inválido

  • SecurityException - quando o arquivo de link não pode ser criado ou o arquivo de destino não pode ser acessado devido a permissões de arquivo limitadas

Agora, se temos um determinado sistema de arquivos com links de arquivos existentes, é possível identificá-los e mostrar seus arquivos de destino:

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

Se o executarmos em nosso caminho atual:

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

Obteríamos a saída:

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 são necessários para trabalhar com esse tipo de arquivo.

5. Conclusão

Este artigo descreve os diferentes tipos de links de arquivos, sua diferença com os atalhos e como criar e operar sobre eles usando uma API Java pura que funciona nos sistemas de arquivos principais do mercado.

A implementação desses exemplos e trechos de código pode ser encontradaover on GitHub.