解析具有嵌套结构的纯文本文件

时间:2014-11-20 17:15:01

标签: java parsing

我正在尝试将纯文本文件解析为ArrayList Objects。问题是它有某种嵌套结构。数据如下所示:

S   183166621   75783-29-8          0   -1  0   0   0   0
SS  183166621   0   DE  Siloxane und Silikone, di-Me, polymers mit bor oxid (B2O3)
SS  183166621   0   EN  Siloxanes and Silicones, di-Me, polymers with boron oxide (B2O3)
S   183166624   3087-36-3       221-410-8   0   -1  0   0   0   0
SS  183166624   0   DE  Titan(4+)ethanolat
SS  183166624   0   EN  Ethanol, titanium(4+) salt

所以有一行以“S”开头,代表某种物质。每个“S”行后面跟着多个“SS”行,其中包含不同语言中相应物质的同义词。同义词的数量不固定。有些只有2个,有些有3个,4个或更多。

我的想法是创建一个Substance Object,其中包含一个包含所有可能的同义词的列表。

我创建了一个BufferedReader并尝试逐行解析文件

String line;
while((line = br.readLine()) != null) {
    if (line.startsWith("S\t")) {

        Substance substance = new Substance();
        String[] columns = line.split("\t");

        // Parse columns and store them in substance Object

    }
}

要读取同义词,我想启动第二个内部循环,解析以“SS”开头的所有行。当到达另一个“S”时,内循环停止。

String line;
while((line = br.readLine()) != null) {
    if (line.startsWith("S\t")) {

        Substance substance = new Substance();
        String[] columns = line.split("\t");

        // Parse columns and store them in substance Object

        while((line = br.readLine()) != null) {
            if (line.startsWith("SS\t")) {
                Synonym synonym = new Synonym();

                // Parse columns and store them in synonym Object

                // Add synonym to List of Synonyms of Substance 
                substance.addSynonym(synonym);
            }
            else {
                break;
            }
        }
    }
}  

这个问题是,在离开内循环后,外循环执行另一个readline(),因此实际的“S” - 失去了。

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:3)

您已经认识到的问题是您从阅读器中读过两次。我只读一次并立即拆分,检查主要物质的第一个标记是S还是先前读过的主要物质的同义词SS。为此,您需要在循环之外使用Substance substance;变量。

String line;
Substance actualSubstance = null;
while((line = br.readLine()) != null) {
    String[] columns = line.split("\t");
    if (columns[0].equals("S")) {
        actualSubstance = new Substance();
        // parse main substance
    } else if (columns[0].equals("SS")) {
        if(actualSubstance != null) {
            Synonym synonym = new Synonym(); 
            // parse synonim substance and add to actual main substance
            actualSubstance.addSynonym(synonym);
        } else {
            // bad format of the input file -> handle accordingly 
        }
    } else {
        // junk
    }
}

答案 1 :(得分:1)

解决此问题的常用方法之一是保持引用变量引用您创建的最后一个Substance对象。您可以在循环外定义变量。

然后你开始解析这些行。

如果该行以单个S开头,则检查substance的先前值是否不是null。如果是这样,您将其添加到物质列表中。然后,您创建一个新的Substance并将其分配给substance

这样,每次点击Substance行时都会开始新的S,并在看到新的S行后立即将其放入列表中。< / p>

在同一循环中,如果该行以SS开头,则解析同义词,并使用substance.addSynonym。您知道在此阶段您已经创建了Substance对象,并且它正在substance中等待。如果您不确定文件始终以S开头,建议您检查null

最后,在循环结束后,Substance中的substance对象尚未提交到列表中,因为没有新的S行。您只需将其添加到列表中即可。

ArrayList<Substance> list = new ArrayList<>();
String line;
Substance substance = null ;

while((line = br.readLine()) != null) {

    if (line.startsWith("S\t")) {

        if ( substance != null ) {
           list.add( substance );
        }

        substance = new Substance();
        String[] columns = line.split("\t");

        // Parse columns and store them in substance Object

    else if (line.startsWith("SS\t")) {
        Synonym synonym = new Synonym();

        // Parse columns and store them in synonym Object

        // Add synonym to List of Synonyms of Substance 
        if ( substance != null ) {
            substance.addSynonym(synonym);
        }
    }
}
list.add( substance );