Однозначно идентифицировать файл в Java

Я работаю в 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 имеют разную структуру и управляются разными системными вызовами ...

Простите за незнание, но разве путь в файловой системе (например, /home/user/file.txt) не идентифицирует файл?

Karol Dowbecki 26.12.2018 19:23

@KarolDoabecki К сожалению, идентификация просто по пути к файлу недопустима для переименования и подвержена условиям гонки, если мы работаем с файлами одновременно.

Some Name 26.12.2018 19:24

@KarolDowbecki не в случае символической ссылки

HairOfTheDog 26.12.2018 19:25
если (и это большое, если) вам нужно использовать собственный маршрут, и в зависимости от ваших требований к производительности я бы предложил использовать JNA вместо JNI, потому что JNA не требует, чтобы вы писали собственную библиотеку поддержки. Я был удивлен тем, насколько легко было использовать JNA. github.com/java-native-access/jna
HairOfTheDog 26.12.2018 19:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
4
463
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Этот пример 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 двух файлов может быть одинаковым (даже маловероятным), если они находятся в разных каталогах, которые находятся в разных файловых системах ... не так ли?

Some Name 26.12.2018 19:31

Или этот inode также включает fsid ...?

Some Name 26.12.2018 19:33

@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/…

HairOfTheDog 26.12.2018 19:47

Похоже, это именно то, что мне нужно. Спасибо!

Some Name 26.12.2018 19:49

@SomeName, что именно вы хотите сделать с файловым ключом? Если вы просто хотите узнать, являются ли два файла одинаковыми, просто используйте метод equals объекта, возвращенного attr.fileKey(). Пока вы не пытаетесь интерпретировать объект как индексный дескриптор, вам не придется сталкиваться с неоднозначностью индексных дескрипторов (различных хранилищ файлов).

Holger 07.01.2019 13:52

@Holger Я намерен сохранять некоторое состояние обработки файла каждый раз, когда файлы изменяются. Так что я однозначно идентифицирую каждый файл по ключу. Поскольку я слушаю события inotify в каталогах несколько (настраивается), поэтому они могут не использовать одну и ту же файловую систему, и просто inode недостаточно. Проблема в том, что другой процесс может переименовать файл в каталоге, в котором он содержится, поэтому я решил сначала открыть файл и получить его файловый дескриптор. С помощью дескриптора файла я могу получить ключ и быть защищенным от переименования. Сценарий выглядит разумным?

Some Name 08.01.2019 10:41

@SomeName не совсем ясно, в какой момент действительно требуется использование кода Java или машинного кода. В Java NIO есть способ однозначной идентификации файлов (это делает объект, возвращаемый fileKey()), а также абстракция службы наблюдения. Обратите внимание, что код ответа идет очень долго, чтобы разрушить уникальность ключа файла. Сначала он преобразует его в String, а затем извлекает из него неуникальный индексный дескриптор. Если вы посмотрите на исходное строковое представление, вы увидите что-то вроде "(dev=xxx,inode=yyy)", явно намекающее на тот факт, что ключевой объект однозначно идентифицирует файл.

Holger 08.01.2019 13:51

@Holger Может быть, это перебор, но я действительно не знаю, как решить проблему строго на Java. К сожалению, WatchService не поддерживает события MOVED_FROM / MOVED_TO и рассматривает их как DELETE / CREATE, так что в моем случае он отсутствует. Также я не могу просто использовать Path, полученный от struct inotify_event, для получения атрибута, потому что файл от Path может быть перемещен, и при обработке события создается новый. Таким образом, весь ввод-вывод в настоящее время выполняется через оболочки функций JNI.

Some Name 08.01.2019 14:12

Я бы предложил метод GIT для хеширования содержимого файла. Это защита от копирования и переименования.

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

Это именно то решение, которое я использую сейчас ... Но, к сожалению, оказалось, что оно не обладает необходимой гибкостью.

Some Name 26.12.2018 19:32

@ Какое-нибудь имя, не могли бы вы уточнить?

Jonathan Rosenne 27.12.2018 05:11

Другие вопросы по теме