Я работаю в Linux, и мое приложение Java не предназначено для переносимости.
Я ищу способ однозначно идентифицировать файл в Java. Я могу использовать системный вызов statfs, поскольку пара (f_fsid, ino) однозначно идентифицирует файл (не только в файловой системе), как указано здесь: http://man7.org/linux/man-pages/man2/statfs.2.html
Вопрос в том, можно ли извлечь fsid из Java напрямую, чтобы я не писал функцию JNI?
inode можно извлечь с помощью NIO, но как насчет fsid? inode и fsid имеют разную структуру и управляются разными системными вызовами ...
@KarolDoabecki К сожалению, идентификация просто по пути к файлу недопустима для переименования и подвержена условиям гонки, если мы работаем с файлами одновременно.
@KarolDowbecki не в случае символической ссылки




Этот пример java демонстрирует, как получить номер inode файла в формате unix.
import java.nio.file.*;
import java.nio.file.attribute.*;
public class MyFile {
public static void main(String[] args) throws Exception {
BasicFileAttributes attr = null;
Path path = Paths.get("MyFile.java");
attr = Files.readAttributes(path, BasicFileAttributes.class);
Object fileKey = attr.fileKey();
String s = fileKey.toString();
String inode = s.substring(s.indexOf("ino = ") + 4, s.indexOf(")"));
System.out.println("Inode: " + inode);
}
}
Выход
$ java MyFile
Inode: 664938
$ ls -i MyFile.java
664938 MyFile.java
кредит, по которому подлежит оплате: https://www.javacodex.com/More-Examples/1/8
Если мы работаем в одной файловой системе, все работает нормально. Но inode двух файлов может быть одинаковым (даже маловероятным), если они находятся в разных каталогах, которые находятся в разных файловых системах ... не так ли?
Или этот inode также включает fsid ...?
@SomeName Как насчет FileStore, к которому вы можете получить доступ через Files.getFileStore? docs.oracle.com/javase/8/docs/api/java/nio/file/FileStore.ht mldocs.oracle.com/javase/8/docs/api/java/nio/file/…
Похоже, это именно то, что мне нужно. Спасибо!
@SomeName, что именно вы хотите сделать с файловым ключом? Если вы просто хотите узнать, являются ли два файла одинаковыми, просто используйте метод equals объекта, возвращенного attr.fileKey(). Пока вы не пытаетесь интерпретировать объект как индексный дескриптор, вам не придется сталкиваться с неоднозначностью индексных дескрипторов (различных хранилищ файлов).
@Holger Я намерен сохранять некоторое состояние обработки файла каждый раз, когда файлы изменяются. Так что я однозначно идентифицирую каждый файл по ключу. Поскольку я слушаю события inotify в каталогах несколько (настраивается), поэтому они могут не использовать одну и ту же файловую систему, и просто inode недостаточно. Проблема в том, что другой процесс может переименовать файл в каталоге, в котором он содержится, поэтому я решил сначала открыть файл и получить его файловый дескриптор. С помощью дескриптора файла я могу получить ключ и быть защищенным от переименования. Сценарий выглядит разумным?
@SomeName не совсем ясно, в какой момент действительно требуется использование кода Java или машинного кода. В Java NIO есть способ однозначной идентификации файлов (это делает объект, возвращаемый fileKey()), а также абстракция службы наблюдения. Обратите внимание, что код ответа идет очень долго, чтобы разрушить уникальность ключа файла. Сначала он преобразует его в String, а затем извлекает из него неуникальный индексный дескриптор. Если вы посмотрите на исходное строковое представление, вы увидите что-то вроде "(dev=xxx,inode=yyy)", явно намекающее на тот факт, что ключевой объект однозначно идентифицирует файл.
@Holger Может быть, это перебор, но я действительно не знаю, как решить проблему строго на Java. К сожалению, WatchService не поддерживает события MOVED_FROM / MOVED_TO и рассматривает их как DELETE / CREATE, так что в моем случае он отсутствует. Также я не могу просто использовать Path, полученный от struct inotify_event, для получения атрибута, потому что файл от Path может быть перемещен, и при обработке события создается новый. Таким образом, весь ввод-вывод в настоящее время выполняется через оболочки функций JNI.
Я бы предложил метод GIT для хеширования содержимого файла. Это защита от копирования и переименования.
Предполагается, что Java не зависит от платформы, поэтому использование методов, специфичных для Unix, может быть не тем, что вам нужно.
Это именно то решение, которое я использую сейчас ... Но, к сожалению, оказалось, что оно не обладает необходимой гибкостью.
@ Какое-нибудь имя, не могли бы вы уточнить?
Простите за незнание, но разве путь в файловой системе (например,
/home/user/file.txt) не идентифицирует файл?