将纯文本解析为某个结构化对象

Jer*_*iho 5 java parsing key-value

我正在解析纯文本并将其转换为键值对.例如,纯文本:

some_uninteresting_thing
key1 valueA, some_uninteresting_thing  valueB
key2 valueD
key3 some_uninteresting_thing  valueE 
key4 valueG(valueH, valueI)
key5 some_uninteresting_thing 
Run Code Online (Sandbox Code Playgroud)

可能的映射:

 Map(

 key1 ->(valueA, valueB,valueC), 
 key2 ->(valueD, valueE),
 key3 ->(valueF)
 key4 ->(valueH, valueI)

 ...
 )
Run Code Online (Sandbox Code Playgroud)

Amd结果将是:

key1 ->(valueA, valueB)
key2 ->(valueD)
key4 ->(valueH, valueI)
Run Code Online (Sandbox Code Playgroud)

(key5不应该映射,因为没有适当的值.正如你所看到的那样,纯文本是宽松的.什么java库有助于处理这个?

mdm*_*dma 3

如果您熟悉形式语言、标记化/语法等,您可以使用解析器生成器,例如JavaCC。JavaCC 获取您编写的语法文件并生成 java 代码,将文本文件解析为一系列标记或语法树。Maven 和 Ant 的插件可以帮助将此附加源集成到您的构建中。

对于仅运行时的解决方案,有RunCC,我使用它取得了良好的效果。(我怀疑它不如 JavaCC 快,但就我而言,性能还不错。)

还有Chaperon,它使用语法文件将纯文本转换为 XML。

这些的替代方法是使用正则表达式和StringTokenizer.

解析器项目或正则表达式准备就绪后,您的一般方法如下所示:

  1. 为纯文本文件编写语法。纯文本格式缺少一些详细信息,但您可以简单地使用 aBufferedReader.readLine()来读取文件的行,并StringTokenizer以空格和逗号将行拆分为子字符串。
  2. 您从解析器获得的字符串、用作键的第一个字符串以及随后的字符串是您添加到 Map 的值。例如在伪代码中

    映射>映射=新的HashMap>(); 对于每一行 { 列出标记 = ...; // 分割行的结果 String key = tokens.get(0); map.add(key, tokens.sublist(1, tokens.size()); }

    即使解析器不过滤不感兴趣的文本,它也会在稍后被过滤。

  3. 使用上述项目构建一个解析器来解析地图文件格式。同样,您也许可以使用正则表达式和 StringTokenizer 构建一个简单的解析器。使用解析器构建地图。该地图具有与上面相同的签名,即Map<String,List<String>>.

  4. 最后,根据允许值映射过滤输入映射。

像这样的东西。

   Map<String,List<String>> input = ...; // from step 1.
   Map<String,List<String>> allowed = ...; // from step 3.
   Map<String,List<String>> result = new HashMap<String<list<String>>(); // the final map
   for (String key : input.keySet()) {
      if (allowd.contains(key)) {
         List<String> outputValues = new ArrayList();
         List<String> allowedValues = allowed.get(key);
         List<String> inputValues = input.get(key);
         for (String value: inputValues) {
            if (allowedValues.contains(value))
                outputValues.add(value);
         }
         if (!outputValues.isEmpty())
            output.put(key, outputValues);
      }
   }
   // final result in filter
Run Code Online (Sandbox Code Playgroud)