BufferedReader和Java中的多行枚举

BufferedReader和Java中的多行枚举,java,bufferedreader,enumeration,owl,ontology,Java,Bufferedreader,Enumeration,Owl,Ontology,我正在制作一个java应用程序,它逐行读取.ttl文件,并创建一个graphml文件来表示本体 我在计算如何列举某一部分时遇到了一些困难 我正在使用BufferedReader阅读每一行 例如,我有以下几点: else if (line.contains("owl:oneOf")){ // insert code to enumerate list contained in ( ) } 这就是其中一个.ttl的外观: owl:oneOf (GUIFlow:ExactlyO

我正在制作一个java应用程序,它逐行读取
.ttl
文件,并创建一个
graphml
文件来表示本体

我在计算如何列举某一部分时遇到了一些困难

我正在使用
BufferedReader
阅读每一行

例如,我有以下几点:

else if (line.contains("owl:oneOf")){

    // insert code to enumerate list contained in ( )

}
这就是其中一个.ttl的外观:

    owl:oneOf  (GUIFlow:ExactlyOne
                GUIFlow:OneOrMore
                GUIFlow:ZeroOrMore
                GUIFlow:ZeroOrOne ) 

我需要将这4个对象作为一个列表返回,作为本体图形表示的一部分使用。

显然,文件中有某种循环。以下是一些想法:

1)在循环中引入一个“状态”,这样在阅读下一行时,它就会知道它实际上在列表中。存储列表的动态数组可以用作状态。遇到
)时创建列表,遇到
时将列表发送到需要的任何位置。
,然后删除该列表。一个复杂的情况是,根据源格式,您必须在向列表添加值之前创建列表,并在添加值之后处理和删除列表,因为
与实际值位于同一行

Vector<String> oneOfList = null;

while(reader.ready()){
    String line=reader.readLine();

    if(line.contains("foo")){
        ...
    }
    else if (line.contains("owl:oneOf")){
        oneOfList = new Vector<String>();
    }

    if(oneOfList!=null){
        String str = line.trim();
        int a = str.indexOf("(");  // -1 if not found, OK
        int b = str.indexOf(")");
        if(b<0) b=str.length();
        oneOfList.add(str.substring(a+1,b).trim());
    }

    if (line.contains(")")){
        storeOneOf(oneOfList);
        oneOfList=null;
    }

}
3)上述算法依赖于这样一个事实,即头文件
和第一个值在同一行,以此类推。如果源文件的格式稍有不同,解析将失败。更灵活的方法可能是使用
StreamTokenizer
,它会自动忽略空白并将文本分隔为单词和独立符号:

StreamTokenizer tokzr=new StreamTokenizer(reader);
tokzr.wordChars(':',':');

while( tokzr.nextToken() != tokzr.TT_EOF ){
    if( tokzr.ttype==tokzr.TT_WORD && tokzr.sval.equals("foo") ){
        ...
    }
    else if ( tokzr.ttype==tokzr.TT_WORD && tokzr.sval.equals("owl:oneOf") ){
        if(tokzr.nextToken()!='(') throw new Exception("\"(\" expected");
        Vector<String> oneOfList = new Vector<String>();
        while(tokzr.nextToken() == tokzr.TT_WORD){
            oneOfList.add(tokzr.sval);
        }
        storeOneOf(oneOfList);
        if(tokzr.ttype!=')') throw new Exception("\")\" expected");
    }
}
StreamTokenizer tokzr=新的StreamTokenizer(读卡器);
tokzr.wordChars(“:”,“:”);
while(tokzr.nextToken()!=tokzr.TT_EOF){
if(tokzr.ttype==tokzr.TT_WORD&&tokzr.sval.equals(“foo”)){
...
}
else if(tokzr.ttype==tokzr.TT_WORD&&tokzr.sval.equals(“owl:oneOf”)){
if(tokzr.nextToken()!='(')抛出新异常(“\”(\”预期”);
Vector oneOfList=新向量();
while(tokzr.nextToken()=tokzr.TT_单词){
添加(tokzr.sval);
}
storeOneOf(列表中的一个);
if(tokzr.ttype!='))抛出新异常(“预期”);
}
}

显然,您在文件中有某种循环。以下是一些想法:

1)在循环中引入一个“状态”,这样在读取下一行时,它就会知道它实际上在oneOf列表中。存储列表的动态数组可以用作状态。当遇到
)时,您会创建列表,当遇到
时,您会将列表发送到需要的任何地方
,然后删除列表。一个复杂的问题是,根据源格式,您必须在向列表添加值之前创建列表,并在添加值之后处理和删除列表,因为
与实际值在同一行

Vector<String> oneOfList = null;

while(reader.ready()){
    String line=reader.readLine();

    if(line.contains("foo")){
        ...
    }
    else if (line.contains("owl:oneOf")){
        oneOfList = new Vector<String>();
    }

    if(oneOfList!=null){
        String str = line.trim();
        int a = str.indexOf("(");  // -1 if not found, OK
        int b = str.indexOf(")");
        if(b<0) b=str.length();
        oneOfList.add(str.substring(a+1,b).trim());
    }

    if (line.contains(")")){
        storeOneOf(oneOfList);
        oneOfList=null;
    }

}
3)上述算法依赖于这样一个事实,即头文件
和第一个值在同一行,以此类推。如果源文件的格式稍有不同,解析将失败。更灵活的方法可能是使用
StreamTokenizer
,它会自动忽略空白并将文本分隔为单词和独立符号:

StreamTokenizer tokzr=new StreamTokenizer(reader);
tokzr.wordChars(':',':');

while( tokzr.nextToken() != tokzr.TT_EOF ){
    if( tokzr.ttype==tokzr.TT_WORD && tokzr.sval.equals("foo") ){
        ...
    }
    else if ( tokzr.ttype==tokzr.TT_WORD && tokzr.sval.equals("owl:oneOf") ){
        if(tokzr.nextToken()!='(') throw new Exception("\"(\" expected");
        Vector<String> oneOfList = new Vector<String>();
        while(tokzr.nextToken() == tokzr.TT_WORD){
            oneOfList.add(tokzr.sval);
        }
        storeOneOf(oneOfList);
        if(tokzr.ttype!=')') throw new Exception("\")\" expected");
    }
}
StreamTokenizer tokzr=新的StreamTokenizer(读卡器);
tokzr.wordChars(“:”,“:”);
while(tokzr.nextToken()!=tokzr.TT_EOF){
if(tokzr.ttype==tokzr.TT_WORD&&tokzr.sval.equals(“foo”)){
...
}
else if(tokzr.ttype==tokzr.TT_WORD&&tokzr.sval.equals(“owl:oneOf”)){
if(tokzr.nextToken()!='(')抛出新异常(“\”(\”预期”);
Vector oneOfList=新向量();
while(tokzr.nextToken()=tokzr.TT_单词){
添加(tokzr.sval);
}
storeOneOf(列表中的一个);
if(tokzr.ttype!='))抛出新异常(“预期”);
}
}

您是否考虑(并拒绝)现有解决方案,例如:?

您是否考虑(并拒绝)现有解决方案,例如:?

您是否会根据当前状态解析行并解释行内容,即如果您以前遇到过(您知道您有元素
owl:oneOf
和列表的开头,因此下面是列表元素,直到遇到相应的
。我建议不要从头开始编写海龟解析器。有各种API已经允许解析,其中许多是开源的,因此您可以直接使用它们或扩展/重用代码以适合您的应用程序。在@david soroko的回答中提到的Sesame和Jena是两个很好的起点。您应该解析这行代码并解释line内容取决于当前状态,即,如果您以前遇到过
owl:oneOf(
您知道您有元素
owl:oneOf
和列表的开头,那么接下来是列表元素,直到遇到相应的
。我建议不要从头开始编写海龟解析器。有各种API已经允许解析,其中许多是开源的,因此您可以直接使用它们或扩展/重用代码以适合您的应用程序。在@david soroko的回答中提到的Sesame和Jena是两个很好的起点。是的,我有一个很长的循环。我真的我喜欢StreamTokenizer的想法,但我一定会尝试每种方法,看看哪种方法最有效。非常感谢您给出如此详尽的答案!是的,我还有一段时间要做。我非常喜欢StreamTokenizer的想法,但我一定会尝试每种方法,看看哪种方法最有效。非常感谢您给出如此详尽的答案!