Используя альтернативу для выключателя/Государственный таможенный парсер


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

Сейчас, этот инструмент также поддерживает сохранение все ваш матч/заменить-пар в файл. С тех пор как я сделал плохой опыт при использовании ДСЫН со списками или массивами в прошлом, я решил использовать свой собственный формат - считая ее просто нужно сохранить какой-то match-replace-separator-match-replace-separator-etc-стиль структуры.

Теперь, мой код работает так далеко, но во время рефакторинга, я чувствовал, что с помощью переключателя-заявление с государствами для парсинга мой формат-это некрасиво и/или плохой стиль.
Однако, если вы считаете, что это на самом деле хорошее решение, вопреки моей оценке, я бы конечно тоже доволен вашим ответом.

В private static final int значения в данном фрагменте ниже будут заменены с помощью enum, в конце концов, но для этого, я решил, что это будет более читабельным (за счет устранения необходимости для дополнительных классов).

private static final String SEPARATOR = "###";
private static final int SEPARATOR_EXPECTED = 0;
private static final int MATCH_EXPECTED = 1;
private static final int REPLACE_EXPECTED = 2;

public static List<MatchReplacePair> readRegexesFromFile(File file) {
    List<MatchReplacePair> list = new ArrayList<>();
    try (BufferedReader br = new BufferedReader(new FileReader(file))) {
        String line = br.readLine();
        int state = SEPARATOR_EXPECTED;
        MatchReplacePair pair = new MatchReplacePair("", "");
        while (line != null) {
            switch (state) {
            case SEPARATOR_EXPECTED:
                if (line.startsWith(SEPARATOR)) {
                    state = MATCH_EXPECTED;
                } else {
                    throw new IllegalStateException("Separator expected, but not found.");
                }
                break;
            case MATCH_EXPECTED:
                pair.setMatch(line);
                state = REPLACE_EXPECTED;
                break;
            case REPLACE_EXPECTED:
                pair.setReplace(line);
                // note: I have overridden the clone() method for this purpose, so it actually does what it's supposed to.
                list.add(pair.clone());
                state = SEPARATOR_EXPECTED;
                break;
            default:
                throw new IllegalStateException("Unknown state. Please contact the developer.");
            }
            line = br.readLine();
        }
        if (state != SEPARATOR_EXPECTED) {
            throw new IllegalStateException(
                    "Incorrect file contents: make sure the file ends with a \"replace\" block.");
        }
    } catch (IOException e) {
        e.printStackTrace(log);
    }
    return list;
}

Пример файла для анализа:

### //This is where one could write comments if one was so inclined.
match
replace


107
1
задан 8 февраля 2018 в 05:02 Источник Поделиться
Комментарии
1 ответ

Хотя вы не поделитесь MatchReplacePair Я предполагаю, что он содержит строки, которые были загружены из файла. Так ведь вы прочитали все содержимое файла в память.

Начиная с Java 7, это можно сделать в один вызов метода:

List<String> lines = Files.readAllLines(file.toPath());

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

if (lines.size() % 3 != 0) {
// Incorrect file contents
}
Iterator<String> itr = lines.iterator();
// the above check ensures you can iterate over three lines safely
while (itr.hasNext()) {
itr.next(); // ignore separator line? or you can verify if you wish
list.add(new MatchReplacePair(itr.next(), itr.next()));
}

Это также устраняет необходимость для clone() который был использован в качестве конструктора замену.

1
ответ дан 8 февраля 2018 в 09:02 Источник Поделиться