【问题标题】:Key value parser implementation with CSV parser in javajava中使用CSV解析器的键值解析器实现
【发布时间】:2018-12-14 06:52:05
【问题描述】:

我正在编写一个程序来解析基于键值的日志,如下所示:

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

代码有问题还是解析器错误?

问候,
哈里

【问题讨论】:

    标签: java csv parsing univocity


    【解决方案1】:

    lib 的作者在这里。这不是解析器错误。您在这里遇到的问题是您没有解析 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

    希望这对您有所帮助,感谢您使用我们的解析器!

    【讨论】:

    • 感谢您的回复。我会试试这个。
    【解决方案2】:

    我最终编写了自己的解析器。如果有人需要,我将在这里粘贴以供将来参考。欢迎提出建议和cmets。

    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()]);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-06
      • 2011-07-01
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多