Каков эффективный способ анализа строки в Java? - PullRequest
6 голосов
/ 29 июля 2009

Как мне разобрать следующие String, используя Java для извлечения пути к файлу?

? обозначает любое количество случайных символов

_ обозначает любое количество пробелов (без новой строки)

?[LoadFile]_file_=_"foo/bar/baz.xml"?

Пример:

10:52:21.212 [LoadFile] file = "foo/bar/baz.xml"

должен извлечь foo/bar/baz.xml

Ответы [ 5 ]

12 голосов
/ 29 июля 2009
String regex = ".*\\[LoadFile\\]\\s+file\\s+=\\s+\"([^\"].+)\".*";

Matcher m = Pattern.compile(regex).matcher(inputString);
if (!m.find()) 
    System.out.println("No match found.");
else
    String result = m.group(1);

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

Вам следует взглянуть на класс Pattern для получения справки по регулярным выражениям. Они могут быть очень мощным инструментом для работы со строками.

3 голосов
/ 05 ноября 2010

Краткий ответ: используйте subSequence () .

if (line.contains("[LoadFile]"))
  result = line.subSequence(line.indexOf('"'), line.lastIndexOf('"')).toString();

На моей машине это постоянно занимает менее 10000 нс.

Я понимаю, что «эффективный» означает «быстрее».

Параметр regex значительно медленнее (примерно в 9 или 10 раз медленнее). Основное преимущество опции regex заключается в том, что другому программисту может быть проще выяснить, что вы делаете (но затем используйте комментарии, чтобы помочь им).

Чтобы сделать параметр регулярного выражения более эффективным, предварительно скомпилируйте его:

private static final String FILE_REGEX = ".*\\[LoadFile\\]\\s+file\\s+=\\s+\"([^\"].+)\".*";
private static final Pattern FILE_PATTERN = Pattern.compile(FILE_REGEX);

Но это все равно делает это медленнее. Я записываю времена между 80 000 и 100 000 нс.

Параметр StringTokenizer более эффективен, чем регулярное выражение:

if (line.contains("[LoadFile]")) {
  StringTokenizer tokenizer = new StringTokenizer(line, "\"");
  tokenizer.nextToken();
  result = tokenizer.nextToken();
}

Это колеблется для меня примерно на 40000 нс, что делает его в 2-3 раза быстрее, чем регулярное выражение.

В этом сценарии split () также является опцией, которая для меня (с использованием Java 6_13) немного быстрее, чем Tokenizer:

if (line.contains("[LoadFile]")) {
  String[] values = line.split("\"");
  result = values[1];
}

Для меня это в среднем 35 000 нс.

Конечно, ничего из этого не проверяет на ошибки. Каждый параметр будет немного медленнее, когда вы начнете учитывать это, но я думаю, что параметр subSequnce () все равно превзойдет их всех. Вы должны знать точные параметры и ожидания, чтобы выяснить, насколько отказоустойчивым должен быть каждый параметр.

2 голосов
/ 29 июля 2009

Хотя регулярные выражения хороши и все, вы также можете использовать класс java.util.StringTokenizer, чтобы сделать работу. Преимущество - более дружественный к человеку код.

StringTokenizer tokenizer = new StringTokenizer(inputString, "\"");
tokenizer.nextElement();
String path = tokenizer.nextElement();

И вот, пожалуйста.

1 голос
/ 29 июля 2009

Вы можете сделать регулярное выражение немного короче, чем у jinguy. В основном только RHS без "*.

    String regex = ".* = \"(.*)\"";
1 голос
/ 29 июля 2009

java.util.regex ваш друг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...