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

Я пытаюсь прочитать текстовый файл, написанный в этой форме:

    AB523:[joe, pierre][charlie][dogs,cat]
    ZZ883:[ronald, zigomarre][pele]

Я хотел бы создать свою структуру и правильно получить информацию.

AB523 - одинДжо, Пьер - одинЧарли --- одинсобаки, кошка --- одна

Я не уверен, какой метод лучше использовать.Я пробовал StringTokenizer ... и играл с regEx, но я не могу понять это правильно

У вас есть какое-нибудь решение?или предложение

Что такое соглашение при записи в текстовый файл?Каковы лучшие практики с разделителями?

РЕДАКТИРОВАТЬ: Текстовый файл также сгенерирован мной, поэтому я контролирую общий шаблон.Какой будет лучший выходной шаблон для уменьшения объема работы при его повторном чтении?

Ответы [ 5 ]

2 голосов
/ 01 ноября 2011

Я бы использовал здесь регулярные выражения, потому что кажется, что кода меньше для поддержки, и ваш язык, безусловно, является регулярным.Наряду с экземпляром java.util.Scanner для большей эффективности.Вот некоторый код:

import java.io.Reader;
import java.io.StringReader;
import java.util.Scanner;
import java.util.regex.Pattern;

public class ScannerTest {

private static final Pattern header = Pattern.compile("(.*):");
private static final Pattern names = Pattern.compile("\\[([^\\]]+)\\]");

public static void main(String[] args) {

    Reader reader = new StringReader(
            "AB523:[joe, pierre][charlie][dogs,cat]\n"
                    + "ZZ883:[ronald, zigomarre][pele]");

    Scanner scanner = new Scanner(reader);
    scanner.useDelimiter("\n");

    while (scanner.hasNext()) {
        String h = scanner.findInLine(header);
        // Substring removes trailing ':'.
        System.out.println(h.substring(0, h.length() - 1));

        String n;
        while ((n = scanner.findInLine(names)) != null)
            // Substring removes '[' and ']'.
            System.out.println(n.substring(1, n.length() - 1));

        if (scanner.hasNext())
            scanner.nextLine();
    }
}
}

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

РЕДАКТИРОВАТЬ: для лучшей производительности я бы также рассмотрел ручной анализатор рекурсивного спуска .

1 голос
/ 01 ноября 2011

Используйте String#split или Pattern#split Метод.Например,

   String[] list ="AB523:[joe, pierre][charlie][dogs,cat]".split("[:\\[\\]]+");
   for(String s : list)
       System.out.println(s);
0 голосов
/ 01 ноября 2011

Если вы генерируете файл данных, генерируйте его в стандартном формате, таком как CSV (для простых линейных данных) или Json (для структурированных данных) или даже XML (для интенсивной обработки структурированных данных).

0 голосов
/ 01 ноября 2011

Поскольку у вас есть контроль над форматом файла, я бы предложил разделить табуляцией. Многие другие программы (например, Excel) будут читать табуляции с разделителями. Таким образом, файл будет выглядеть следующим образом (\ t представляет вкладку)

AB523\tjoe, pierre\tcharlie\tdogs,cat
ZZ883\tronald, zigomarre\tpele

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

Как и другие, String.split () - хороший способ разбора файла.

0 голосов
/ 01 ноября 2011

Односимвольные разделители легко разделить: функция String.split () будет разделена на символ или строку.Они делают именно то, что делает StringTokenizer, но делают это с более чистым синтаксисом.То есть String[] items = myString.split(",") выглядит намного чище, чем

StringTokenizer st = new StringTokenizer(myString, ","); 
while(st.hasMoreTokens()){
    myList.add(st.nextToken();
}

(используйте split в будущем - это то, что я говорю.)

Однако похоже, что вы внемного более сложная ситуация, когда вам нужно расположить материал слева [ и справа ].Это требует регулярных выражений и захвата групп.Что-то вроде /\[(.*)\]/

CSV (значения, разделенные запятыми) являются общими для простых табличных данных, и формат даже стандартизирован до некоторой степени.Если вы хотите представить более сложные объекты, вы можете использовать JSON или SOAP.Если вы используете хранилище только для Java, взгляните на встроенные функции сериализации Java.

Поскольку вы используете его локально, и, возможно, вы сохраняете какой-то объект Java для его представления.Одним из способов было бы реализовать Serializable в любом объекте, представляющем ваши данные.

Если вам это не нравится, я бы пошел с JSON, потому что похоже, что вы делаете какую-то древовидную структуру.

...