1. Общ преглед
В този урок ще изследваме различни начини за създаване на символна връзка в Java с помощта на API NIO.2 и ще изследваме разликите между твърдите и меките връзки към файлове.
2. Твърди срещу меки / символни връзки
Първо, нека дефинираме какво представляват файловите връзки и какво е очакваното им поведение. Файловата връзка е указател, който прозрачно препраща към файл, съхраняван във файловата система .
Често недоразумение е мисленето, че файловата връзка е пряк път, така че нека проверим поведението им:
- Пряк път е обикновен файл, който препраща към целевия файл
- Меката / символна връзка е указател на файл, който се държи като файл, към който се свързва - ако целевият файл се изтрие, тогава връзката е неизползваема
- Твърдата връзка е файлов указател, който отразява файла, към който се свързва, така че всъщност е като клонинг. Ако целевият файл се изтрие, файлът с връзки все още е валиден
Повечето операционни системи (Linux, Windows, Mac) вече поддържат меки / твърди файлови връзки, така че не би трябвало да е проблем да работите над тях с помощта на NIO API.
3. Създаване на връзки
Първо, трябва да създадем целеви файл, към който да се свържем, така че нека да подредим някои данни във файл:
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 - когато възникне грешка в IO, например невалиден път на файла
- SecurityException - когато файлът с връзки не може да бъде създаден или целевият файл не може да бъде достъпен поради ограничени разрешения на файла
4. Операции с връзки
Сега, ако имаме дадена файлова система със съществуващи файлови връзки, възможно е да ги идентифицираме и да покажем целевите им файлове:
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'
Имайте предвид, че файловете с твърди връзки не могат да се идентифицират просто с API на NIO, за да се работи върху този тип файлове са необходими операции на ниско ниво.
5. Заключение
Тази статия описва различния тип файлови връзки, тяхната разлика с преките пътища и как да ги създавате и оперирате с помощта на чист Java API, който работи върху основните файлови системи на пазара.
Прилагането на тези примери и кодови фрагменти може да бъде намерено в GitHub.