Как разделить путь независимо от платформы?

Я использую следующий код, чтобы получить массив со всеми подкаталогами по заданному пути.

String[] subDirs = path.split(File.separator); 

Мне нужен массив, чтобы проверить, находятся ли определенные папки в нужном месте на этом пути. Это выглядело как хорошее решение, пока findBugs не пожаловался, что File.separator используется как регулярное выражение. Кажется, что передача разделителя файлов Windows функции, которая строит из него регулярное выражение, является плохой идеей, потому что обратная косая черта является escape-символом.

Как я могу разделить путь кросс-платформенным способом без использования File.separator? Или такой код подойдет?

String[] subDirs = path.split("/"); 

person Janusz    schedule 08.07.2009    source источник


Ответы (6)


Используйте path.getParentFile() несколько раз, чтобы получить все компоненты пути.

Не рекомендуется использовать path.replaceAll("\\", "/").split("/").

person akarnokd    schedule 08.07.2009
comment
+1 есть хакерские способы сделать это и написать, как это сделать. это правильный путь, и он избавит вас от многих проблем по сравнению с разделением с помощью '/', '\', ‹вставного символа для ОС, о котором вы совсем забыли здесь› - person ShuggyCoUk; 08.07.2009
comment
Да, я ударил обескураженный путь. Извини. - person akarnokd; 08.07.2009

Литерализация строк шаблонов

Всякий раз, когда вам нужно буквально преобразовать произвольноеString в шаблон регулярного выражения, используйте Pattern.quote:

Из API:

public static String quote(String s)

Возвращает буквенный шаблон String для указанного String. Этот метод создает String, который можно использовать для создания Pattern, который будет соответствовать строке s, как если бы это был буквальный шаблон. Метасимволы или управляющие последовательности во входной последовательности не будут иметь специального значения.

Параметры: s — строка, которая должна быть литерализована
Возвращает: замена буквальной строки.

Это означает, что вы можете сделать следующее:

String[] subDirs = path.split(Pattern.quote(File.separator));

Буквенное замещение строк

Если вам нужно буквально преобразовать произвольную замену String, используйте Matcher.quoteReplacement.

Из API:

public static String quoteReplacement(String s)

Возвращает буквальную замену String для указанного String. Этот метод создает String, который будет работать как буквальная замена s в методе appendReplacement класса Matcher. Полученное String будет соответствовать последовательности символов в s, рассматриваемой как буквенная последовательность. Косая черта ('\') и знак доллара ('$') не будут иметь особого значения.

Параметры: s — строка, которая должна быть литерализована
Возвращает: замена буквальной строки.

Эта цитируемая замена String также полезна в String.replaceFirst и String.replaceAll:

Обратите внимание, что обратная косая черта (\) и знаки доллара ($) в строке замены могут привести к тому, что результаты будут отличаться от результатов, если бы она рассматривалась как буквальная строка замены. Используйте Matcher.quoteReplacement для подавления специального значения этих символов, если это необходимо.


Примеры

    System.out.println(
        "O.M.G.".replaceAll(".", "!")
    ); // prints "!!!!!!"

    System.out.println(
        "O.M.G.".replaceAll(Pattern.quote("."), "!")
    ); // prints "O!M!G!"

    System.out.println(
        "Microsoft software".replaceAll("so", "$0")
    ); // prints "Microsoft software"

    System.out.println(
        "Microsoft software".replaceAll("so", Matcher.quoteReplacement("$0"))
    ); // prints "Micro$0ft $0ftware"
person polygenelubricants    schedule 29.04.2010

Создайте пустой список и используйте forEach для перебора элементов пути, вставляя каждый из них в список для последующего использования:

List<String> pathElements = new ArrayList<>();
Paths.get("/foo/bar/blah/baz").forEach(p -> pathElements.add(p.toString()))

Кроме того, если вам нужен определенный элемент пути, используйте:

<pathObject>.getName(<intIndex>).toString() 

где <pathObject> возвращается вызовом Paths.get(), и если вам нужно несколько частей пути, возвращаемых в строке, используйте:

<pathObject>.subPath(<intStart>, <intEnd>).toString()

Вы можете получить общее количество элементов пути (для использования в <intEnd>) с помощью:

<pathObject>.getNameCount()

Существуют и другие полезные методы в Path и пути doc страницы.

person sabujp    schedule 08.06.2018
comment
Пожалуйста, добавьте объяснение, почему ваш код работает и как он решает проблемы в вопросе - person Gergely Toth; 08.06.2018
comment
Если это дает решение, пожалуйста, дайте объяснение, иначе ответ будет удален. - person Ashish Ratan; 08.06.2018

java.nio.file.Path реализует Iterable<Path>, поэтому вы можете сделать:

public static void showElements(Path p) {
    List<String> nameElements = new ArrayList<>();
    for (Path nameElement: p)
        nameElements.add(nameElement.toFile().getName());
    System.out.printf("For this file: [%s], the following elements were found: [%s]\n"
                      , p.toAbsolutePath()
                      , Joiner.on(", ").join(nameElements));
}

Методы getNameCount и getName может использоваться для аналогичной цели.

person Marcus Junius Brutus    schedule 08.03.2016

Вы можете использовать интерфейс Path:

Path p = Paths.get(pathStr);
for (int i = 0; i < p.getNameCount(); i++) {
    String name = p.getName(i).toString();
    //do what you need with name;
}
person alniks    schedule 23.12.2016

Что о

String[] subDirs = path.split(File.separator.replaceAll("\\", "\\\\"));
person Michael    schedule 08.07.2009
comment
Вопрос говорит о кроссплатформенности, у вас работает только для Windows. - person kaiser; 17.02.2021