【问题标题】:How to parse variable space separated text如何解析可变空格分隔的文本
【发布时间】:2014-01-09 21:14:09
【问题描述】:

我需要解析一个日志文件并将其转换为 XML/Excel 文件。日志文件具有以下格式的记录数据:

Key_ID    Property1  Property2 Property3
Row1      value1iiii           value3
Property4
value4
Key_ID    Property1  Property2 Property3
Row2         value1             value3
Property4
value4

目前我正在尝试在 Java 中执行此操作,我需要 XML 转换以进行比较,而 Excel 用于导出(我将使用 Apache POI 库)。问题是元素之间的可变间距,有时值可能是空白的。目前我正在读取两行并将它们存储到一个字符串中并尝试扫描仪,但这会错过空白值并因此解析相应属性的错误值。即使使用正则表达式,也会出现同样的问题。

感谢您的宝贵建议。我保留的数据仅供参考,我的意思是列数不同,有时会有空白值。我已经浏览了近 50 个这样的日志文件,我能发现的共同点是,它打印日志文件就像我们从数据库/Excel 表中复制和粘贴数据一样。我能想到的唯一解决方案是逐个字符地分析一行。 对不起,伙计们,我无法立即回复,我的宽带连接中断了。再次感谢您抽出宝贵时间。

【问题讨论】:

  • Property2 的值​​是否一直为空? Property4 总是换行吗?
  • 列是否有可能是 10 个字符的固定大小,或者每列都有自己的大小?
  • 不确定是否符合格式!属性是否可以包含空格?是否可以假设它们总是至少从列标签“下方”开始。
  • 哦,并且是整个文件中的标题行不变。例如。你能有 Key_ID Property2 Property4 .. Property21
  • 列数是随机的。有时这些值可能是空白的。我已经给出了标题以供参考。

标签: java regex parsing


【解决方案1】:

如果中间有空白字段,则不能使用正则表达式。

但是,如果您的列具有固定宽度,那么我的建议是逐行读取文件。然后使用字符位置解析列。比如1-9是Key_ID,10-20是Property1,以此类推。

【讨论】:

    【解决方案2】:

    这是一种奇怪的格式。 但是,我会假设就是这样。 所以这就是我要做的。 该代码不是 Java 正确的。 更多的是为了说明这个想法。

    while (hasNext()) { // using some reader Scanner can probably work
        String s = nextLine();
        if (s.startsWith("Key_ID")) {
            String s1 = nextLine();
            // requires some complex parsing
            // step 1 - split string into values
            String s11 = s1.split("[ ]+");
            String property1 = null;
            String property2 = null;
            String property3 = null;
            if (s11.length == 1) { // only key is present
            } else if (s11.length == 2) { // two properties have blank values
                // look in the next if block to see how that can expand to 2 blank values
            } else if (s11.length == 3) { // one property have blank values
                if (isBlank(10,20)) { // the text "Property1"
                    property2 = s11[1];
                    property3 = s11[2];
                } else if (isBlank(20,30) { // the text "Property2"
                    property1 = s11[1];
                    property3 = s11[2];
                } else {
                    property1 = s11[1];
                    property2 = s11[2];
                }
            } else {
                property1 = s11[1];
                property2 = s11[2];
                property3 = s11[3];
            }
            nextLine(); // skips the Property4
            String property4 = nextLine();
        }
    }
    
    boolean isBlank(String s, int start, int end) {
        // assumes that if there is a value it will be between the header text (e.g., Property1)
        boolean result = true;
        for (int i = start; i < end; i++) {
            result &= s.charAt(i).equals(' ');
        }
        return result;
    }
    

    注意:可能有进一步优化代码的方法,但我不想深究,因为代码已经很丑陋了。我想指出,因为格式是人类可读但计算机不可读的,所以代码必须有点智能。

    【讨论】:

    • 感谢@Chris,我已经发布了这个,如果有人偶然遇到这种奇怪的格式,所以我会碰到一个魔法图书馆..:P。看来,我得走脏路了。我实际上在发布之前尝试过 split("\\s+") 。
    猜你喜欢
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多