Как проверить, находится ли один файл внутри другого?

1

У меня есть (довольно глупая) проблема, я думаю.

У меня есть два класса File, и я хочу вернуть true если он находится внутри другого. Ложь, если нет. Я не могу просто сравнить родительские файлы, потому что /a/b/c/d также является подпапкой /a/b.

Мой первый подход был примерно таким:

boolean areSubsets(File f1, File f2) {
    if (f1.getAbsolutePath().contains(f2.getAbsolutePath()) ||
            f2.getAbsolutePath().contains(f1.getAbsolutePath()) {
        return true;
    } else {
        return false;
    }
}

Но проблема в том, что существуют ложные срабатывания.

Т.е. если у нас есть f1 с path = /storage/abc и f2 с /storage/abcabc

что вернет true которая не true.

  • 4
    Если вы используете Java 7+, вы должны использовать Path ; у него есть инструменты для этого
  • 1
    Я согласен использовать Path вместо этого, и если вам нужно, то используйте #getCanonicalPath
Показать ещё 3 комментария
Теги:
file

3 ответа

3
Лучший ответ

Вы можете разделить на /:

boolean areSubsets(File f1, File f2) throws IOException {
    String[] p = f1.getCanonicalPath().split("/");
    String[] q = f2.getCanonicalPath().split("/");
    for (int i = 0; i < p.length && i < q.length; i++)
        if (!p[i].equals(q[i]))
            return false;
    return true;
}

Основываясь на комментарии fge, в Java 7 вы можете сделать следующее:

boolean areSubsets(File f1, File f2) {
    Path path1 = f1.toPath();
    Path path2 = f2.toPath();
    return path1.startsWith(path2) || path2.startsWith(path1);
}
  • 0
    #getAbsolutePath подвержен ошибкам для этой задачи. #getCanonicalPath этого используйте #getCanonicalPath . Например, я мог бы создать f1 как new File("../blub/../blub/../blub/abc/sub"); и f2 как new File("abc"); и #getAbsolutePath "потерпит неудачу" здесь.
  • 0
    Кстати, #getCanonicalPath может #getCanonicalPath IOException .
Показать ещё 4 комментария
1

Решение, если вы используете Java 7+:

final Path testedPath = Paths.get(...).toAbsolutePath();
final Path candidateParent = Paths.get(...).toAbsolutePath();

return testedPath.startsWith(candidateParent)
    && !testedPath.equals(candidateParent);

Обратите внимание, что есть.toRealPath(), однако он может генерировать исключение IOException.

1

Один простой подход - использовать startsWith() на путях, но добавить косую черту в "контейнер":

File f1, f2;

boolean contains = f2.getCanonicalPath().startsWith(
    f1.getCanonicalPath() + "/");
  • 2
    #getAbsolutePath подвержен ошибкам для этой задачи. #getCanonicalPath этого используйте #getCanonicalPath . Например, я мог бы создать f1 как new File("../blub/../blub/../blub/abc/sub"); и f2 как new File("abc"); и #getAbsolutePath "потерпит неудачу" здесь.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню