Java использует регулярные выражения для извлечения имени файла - PullRequest
0 голосов
/ 10 октября 2011

Мне нужно получить имя файла по абсолютному пути к файлу (мне известен метод file.getName(), но я не могу использовать его здесь). РЕДАКТИРОВАТЬ: Я не могу использовать file.getName (), потому что мне не нужно только имя файла;Мне также нужна часть пути к файлу (но, опять же, не весь абсолютный путь).Мне нужна часть пути к файлу ПОСЛЕ определенного предоставленного пути.

Допустим, файл находится в папке:

C:\Users\someUser

На компьютере с Windows, если я создаю строку шаблона следующим образом:

String patternStr = "C:\\Users\\someUser\\(.*+)";

Я получаю исключение: java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence для обратной косой черты.

Если я использую Pattern.quote (File.pathSeparator):

String patternStr = "C:" + Pattern.quote(File.separator) + "Users" + Pattern.quote(File.separator) + "someUser" + Pattern.quote(File.separator) + "(.*+)";

полученный шаблонстрока: C:\Q;\EUsers\Q;\EsomeUser\Q;\E(.*+) которая, конечно, не соответствует реальному имени файла "C: \ Users \ someUser \ myFile.txt".

Что мне здесь не хватает?Как правильно проанализировать имя файла?

Ответы [ 10 ]

7 голосов
/ 10 октября 2011

Как правильно проанализировать имя файла?

Правильный способ проанализировать имя файла - использовать File(String).Использование регулярных выражений для этого приводит к жесткой привязке зависимостей платформы к вашему коду.Это плохая идея.

Я знаю, вы сказали, что не можете использовать File.getName() ... но это правильное решение .Если вы хотите сказать, почему вы не можете использовать File.getName(), возможно, я мог бы предложить альтернативное решение.

4 голосов
/ 10 октября 2011

Если вы действительно хотите использовать регулярные выражения, вы должны использовать

String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
                       ^^       ^^          ^^

.

Почему?Ваш строковый литерал

"C:\\Users\\someUser\\(.*+)"

скомпилирован в

C:\Users\someUser\(.*+)

Поскольку \ также используется для экранирования в регулярных выражениях, вам придется экранировать их «дважды».*


По поводу вашего редактирования:

Возможно, вы захотите взглянуть на URI.relativize().Пример:

File base = new File("C:/Users/someUser");
File file = new File("C:/Users/someUser/someDir/someFile.txt");

String relativePath = base.toURI().relativize(file.toURI()).getPath();

System.out.println(relativePath); // prints "someDir/someFile.txt"

(Обратите внимание, что / работает как разделитель файлов и на компьютерах с Windows.)


Кстати, я не знаю, что у вас под именем File.separator в вашей системе, но если он установлен на \, то

"C:" + Pattern.quote(File.separator) + "Users" + Pattern.quote(File.separator) +
    "someUser" + Pattern.quote(File.separator) + "(.*+)";

должно дать

C:\Q\\EUsers\Q\\EsomeUser\Q\\E(.*+)
2 голосов
/ 10 октября 2011
String patternStr = "C:\\Users\\someUser\\(.*+)";

Обратная косая черта (\) - это escape-символы на языке Java. Ваша строка содержит следующее после компиляции:

C:\Users\someUser\(.*+)

Эта строка затем анализируется как регулярное выражение, которое использует обратную косую черту в качестве escape-символа. Парсер регулярных выражений пытается понять экранированные символы \U, \s и \(. Один из них неверен в отношении синтаксиса регулярных выражений (отсюда и ваше исключение), и ни один из них не является тем, чего вы пытаетесь достичь.

Попробуйте

String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
1 голос
/ 10 октября 2011

Если вы хотите решить это по шаблону, вам нужно правильно экранировать свой шаблон

String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
0 голосов
/ 18 мая 2013

Предположим, что имя файла содержит специальные символы, особенно при поддержке MAC, где в именах файлов допускаются специальные символы, Path.GetFileName (fileName) на стороне сервера завершается неудачно и выдает ошибку из-за недопустимых символов в пути.Следующий код, использующий регулярное выражение, приходит на помощь.

Следующий регулярный код заботится о 2 вещах

  1. В IE, когда файл загружен, путь к файлу также содержит папки(то есть c: \ samplefolder \ subfolder \ sample.xls).Приведенное ниже выражение заменит все папки с пустой строкой и сохранит имя файла

  2. При использовании в Mac имя файла - это единственное, что предоставляется в качестве браузера Safari, и допускает специальные символы в имени файла

     var regExpDir = @"(^[\w]:\\)([\w].+\w\\)";
    
     var fileName = Regex.Replace(fileName, regExpDir, string.Empty);
    
0 голосов
/ 10 октября 2011

Я не могу использовать file.getName (), потому что мне не нужно только имя файла; Мне также нужна часть пути к файлу (но опять же, не весь абсолютный путь).

OK. Так что вы хотите что-то вроде этого.

    // Canonicalize paths to deal with ".", "..", symlinks, 
    // relative files and case sensitivity issues.
    String directory = new File(someDirectory).canonicalPath();
    String test = new File(somePathname).canonicalPath();

    if (!directory.endsWith(File.separator)) {
        directory += File.separator;
    }
    if (test.startsWith(directory)) {
        String pathInDirectory = test.substring(directory.length()):
        ...
    }

Преимущества:

  • Не нужно регулярных выражений.
  • Не прерывается, если разделитель пути отличается от \.
  • Не прерывается, если на пути есть символические ссылки.
  • Не ломается из-за проблем с чувствительностью к регистру.
0 голосов
/ 10 октября 2011

Что мне здесь не хватает?Как правильно проанализировать имя файла?

Надлежащим способом анализа имени файла является использование API, уже предоставленных для этой цели.Вы заявили, что не можете использовать File.getName () без объяснения причин.Вы почти наверняка ошибаетесь в этом.

0 голосов
/ 10 октября 2011

Попробуйте это:

String ResultString = null;
try {
    Pattern regex = Pattern.compile("([^\\\\/:*?\"<>|\r\n]+$)");
    Matcher regexMatcher = regex.matcher(subjectString);
    if (regexMatcher.find()) {
        ResultString = regexMatcher.group(1);
    } 
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
}

Выход:

myFile.txt

Также для ввода: C:/Users/someUser/myFile.txt

Выход: myFile.txt

0 голосов
/ 10 октября 2011

Перейти от конца строки к первому вхождению разделителя пути к файлу * или начать.

Разделитель путей к файлам может быть / или \.

public static final char ALTERNATIVE_DIRECTORY_SEPARATOR_CHAR = '/';
public static final char DIRECTORY_SEPARATOR_CHAR = '\\';
public static final char VOLUME_SEPARATOR_CHAR = ':';


    public static String getFileName(String path) {

        if(path == null || path.isEmpty()) {
            return path;
        }

        int length = path.length();
        int index = length;

        while(--index >= 0) {

            char c = path.charAt(index);

            if(c == ALTERNATIVE_DIRECTORY_SEPARATOR_CHAR || c == DIRECTORY_SEPARATOR_CHAR || c == VOLUME_SEPARATOR_CHAR) {
                return path.substring(index + 1, length); 
            }
        }

        return path;
    }

Постарайся сделать это простым; -).

0 голосов
/ 10 октября 2011

Попробуйте добавить двойную двойную обратную косую черту в ваш шаблон. Вам нужен второй обратный слеш, чтобы убежать от одного в шаблоне, плюс вам нужно удвоить каждый из них, чтобы избежать их в строке. Следовательно, вы получите что-то вроде:

String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...