Как сравнить файловую систему двух путей в kotlin/java?

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

path1.fileSystem == path2.fileSystem

потому что может быть случай, когда файловые системы одинаковы по смыслу (они полностью идентичны), но на самом деле являются разными экземплярами и из-за этого path1.fileSystem == path2.fileSystem может вернуться false тогда, когда на самом деле должно вернуться true. Тогда как мне сравнить файловые системы двух разных путей? Или == на самом деле в порядке и работает правильно в этой ситуации?

Я на самом деле пытался задать вопрос

boolean sameFileSystem = FileSystems.getDefault().provider().getScheme().equals(path1.getFileSystem().provider().getScheme())
                && FileSystems.getDefault().provider().getScheme().equals(path2.getFileSystem().provider().getScheme());


Обновление: мне нужно проверить это, чтобы сопоставить один путь с другим. (если файловые системы не одинаковы, я просто сделаю что-нибудь еще, эта часть не имеет значения? Мне просто нужно проверить, совпадают ли они)

Вы действительно наблюдали случай, когда path1.fileSystem == path2.fileSystem возвращался false для той же файловой системы, или вы просто догадываетесь, что это может произойти? Обратите внимание: == в Котлине не проверяет, является ли экземпляр точно таким же, но использует метод equals. Я не совсем уверен, сможем ли мы проверить файловые системы на равенство, и в документации это неясно. Но я хочу сказать: возможно, это работает именно так, как вы ожидаете.

broot 18.04.2024 14:43

Какой язык вы используете для выполнения этого конкретного теста. Java или Котлин?

Stephen C 18.04.2024 14:47

Что именно вы хотите семантически узнать с помощью этой проверки. Зачем вам знать, то же ли это FileSystem? Что же лежит в основе этого различия?

Joachim Sauer 18.04.2024 14:58

Вам нужна та же файловая система или, скорее, тот же поставщик? Ваше обновление не помогает понять вашу проблему. Почему вам нужно использовать другой путь, если файловые системы разные?

Holger 18.04.2024 15:59

@Holger под «использовать другой путь» я имел в виду, что просто сделаю что-нибудь еще, это не очень важно, мне просто нужно проверить, одинаковы ли две файловые системы, чтобы я мог сопоставить один путь с другим

Irina Growl 18.04.2024 16:15

«чтобы я мог сопоставить один путь с другим» — вы можете сопоставить один путь с другим, если они оба принадлежат одному и тому же поставщику файловой системы; им не обязательно принадлежать к одной и той же файловой системе. И даже если они не принадлежат одному и тому же провайдеру, простое преобразование второго пути в строку и вызов resolve(String) вместо resolve(Path) подойдет в 99% всех случаев. Если вы действительно хотите сделать А, но в некоторых случаях прибегаете к Б, важно знать, что такое Б, поскольку это помогает понять, почему вы не переходите к А, несмотря на то, что А — это то, чего вы на самом деле хотите.

Holger 18.04.2024 16:45

@Хольгер, это действительно ответ на мой вопрос, большое спасибо!

Irina Growl 18.04.2024 17:21
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
7
111
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Если вы хотите знать, можете ли вы безопасно вызвать .resolve(Path) для двух существующих экземпляров Path, вы должны проверить, принадлежат ли эти два пути одному и тому же провайдеру, а не файловой системе.

Провайдеров можно сравнивать с помощью оператора ==; они должны быть одиночками.

Для сравнения, вот как Files.copy(…) проверяет, принадлежат ли два пути одному и тому же поставщику файловой системы:

public static Path copy(Path source, Path target, CopyOption... options)
    throws IOException
{
    FileSystemProvider provider = provider(source);
    if (provider(target) == provider) {
        // same provider
        provider.copy(source, target, options);
    } else {
        // different providers
        CopyMoveHelper.copyToForeignTarget(source, target, options);
    }
    return target;
}

private static FileSystemProvider provider(Path path) {
    return path.getFileSystem().provider();
}

В большинстве случаев запасной вариант с использованием .resolve(String) работает, когда вам нужно разрешить пути разных поставщиков файловых систем:

static Path resolveWithForeignSupport(Path base, Path other) {
    FileSystem fs1 = base.getFileSystem(), fs2 = other.getFileSystem();

    if (fs1.provider() == fs2.provider()) {
        return base.resolve(other);
    }

    if (other.getNameCount() <= 1 || fs1.getSeparator().equals(fs2.getSeparator())){
        return base.resolve(other.toString());
    }

    Path resolved = base, othersRoot = other.getRoot();
    if (othersRoot != null) {
        resolved = resolved.resolve(othersRoot.toString());
    }
    for(Path component: other) {
        resolved = resolved.resolve(component.toString());
    }
    return resolved;
}

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