Реализация парсера значения ключа с парсером CSV в Java - PullRequest
0 голосов
/ 14 декабря 2018

Я пишу программу для анализа журнала на основе значений ключей, например:

dstcountry="United States" date=2018-12-13 time=23:47:32

Я использую анализатор Univocity для этого.Вот мой код.

CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.getFormat().setDelimiter(' ');
parserSettings.getFormat().setQuote('"');
parserSettings.getFormat().setQuoteEscape('"');
parserSettings.getFormat().setCharToEscapeQuoteEscaping('"');
CsvParser keyValueParser = new CsvParser(parserSettings);
String line = "dstcountry=\"United States\" date=2018-12-13 time=23:47:32";
String[] resp = keyValueParser.parseLine(line);

Но парсер дает мне такой вывод:

dstcountry="United, 
States", 
date=2018-12-13, 
time=23:47:32

, где ожидаемый вывод был

dstcountry="United States", 
date=2018-12-13, 
time=23:47:32

Есть ли проблемы скод или это ошибка парсера?

С уважением,
Хари

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Автор библиотеки здесь.Это не ошибка парсера.Проблема, с которой вы столкнулись, заключается в том, что вы НЕ анализируете файл CSV.

Когда анализатор видит: dstcountry="United, за которым следует пробел (который является вашим разделителем), он будет рассматривать это как значение.

Параметр кавычки применяется только к полям, начинающимся с символа кавычки.Поскольку ваш ввод не "dstcountry=""United States""", парсер не сможет обработать это так, как вы хотите.Нет парсера CSV, который мог бы сделать это для вас.

Опять же, вы не обрабатываете CSV.Единственное, что вы можете здесь сделать, - это использовать 2 экземпляра синтаксического анализатора: один для разбиения строки вокруг =, а другой - для разбивки значений, разделенных в результате первого синтаксического анализатора.Например:

    CsvParserSettings parserSettings = new CsvParserSettings();
    //break down the rows around the `=` character
    parserSettings.getFormat().setDelimiter('=');

    CsvParser keyValueParser = new CsvParser(parserSettings);
    String line = "dstcountry=\"United States\" date=2018-12-13 time=23:47:32";
    String[] keyPairs = keyValueParser.parseLine(line);

    //break down each value around the whitespace.
    parserSettings.getFormat().setDelimiter(' ');
    CsvParser valueParser = new CsvParser(parserSettings);

    //add all values to a list
    List<String> row = new ArrayList<String>();

    for(String value : keyPairs){
        //if a value has a whitespace, break it down using the the other parser instance
        String[] values = valueParser.parseLine(value);

        Collections.addAll(row, values);
    }

    //here is your result
    System.out.println(row);

Это распечатает:

[dstcountry, United States, date, 2018-12-13, time, 23:47:32]

Теперь у вас есть ключевые значения.Следующий код распечатает это, как вы хотите:

    for (int i = 0; i < row.size(); i += 2) {
        System.out.println(row.get(i) + " = " + row.get(i + 1));
    }

Вывод:

dstcountry = United States

date = 2018-12-13

time = 23:47:32

Надеюсь, это поможет, и спасибо за использование наших парсеров!

0 голосов
/ 15 декабря 2018

В итоге я написал свой собственный парсер.Я вставляю сюда для будущих ссылок, если кто-то нуждается.предложения и комментарии приветствуются.

private static final int INSIDE_QT = 1;
private static final int OUTSIDE_QT = 0;

public String[] parseLine(char delimiter, char quote, char quoteEscape, char charToEscapeQuoteEscaping, String logLine) {
           char[] line = logLine.toCharArray();
    List<String> strList = new ArrayList<>();
    int state = OUTSIDE_QT;
    char lastChar = '\0';
    StringBuffer currentToken = new StringBuffer();
    for (int i = 0; i < line.length; i++) {
        if (state == OUTSIDE_QT) {
            if (line[i] == delimiter) {
                strList.add(currentToken.toString());
                currentToken.setLength(0);
            } else if (line[i] == quote) {
                if (lastChar == quoteEscape) {
                    currentToken.deleteCharAt(currentToken.length() - 1);
                    currentToken.append(line[i]);
                } else {
                    if (removeQuotes == false) {
                        currentToken.append(line[i]);
                    }
                    state = INSIDE_QT;
                }
            } else if (line[i] == quoteEscape) {
                if (lastChar == charToEscapeQuoteEscaping) {
                    currentToken.deleteCharAt(currentToken.length() - 1);
                    currentToken.append(line[i]);
                    continue;
                } else {
                    currentToken.append(line[i]);
                }
            } else {
                currentToken.append(line[i]);
            }
        } else if (state == INSIDE_QT) {
            if (line[i] == quote) {
                if (lastChar != quoteEscape) {
                    if (removeQuotes == false) {
                        currentToken.append(line[i]);
                    }
                    if (currentToken.length() == 0) {
                        currentToken.append('\0');
                    }
                    state = OUTSIDE_QT;
                } else {
                    currentToken.append(line[i]);
                }
            } else if (line[i] == quoteEscape) {
                if (lastChar == charToEscapeQuoteEscaping) {
                    currentToken.deleteCharAt(currentToken.length() - 1);
                    currentToken.append(line[i]);
                    continue;
                } else {
                    currentToken.append(line[i]);
                }
            } else {
                currentToken.append(line[i]);
            }
        }
        lastChar = line[i];
    }
    if (lastChar == delimiter) {
        strList.add("");
    }
    if (currentToken.length() > 0) {
        strList.add(currentToken.toString());
    }
    return strList.toArray(new String[strList.size()]);
}
...