BufferedReader и перечисление нескольких строк в Java
Я нахожусь в процессе создания Java-приложения, которое читает через .ttl
файл строка за строкой и создает graphml
файл для представления онтологии.
У меня возникли проблемы с выяснением, как перечислить определенный раздел.
я использую BufferedReader
читать каждую строку.
Например, у меня есть следующее:
else if (line.contains("owl:oneOf")){
// insert code to enumerate list contained in ( )
}
И вот как выглядит.ttl для oneOf:
owl:oneOf (GUIFlow:ExactlyOne
GUIFlow:OneOrMore
GUIFlow:ZeroOrMore
GUIFlow:ZeroOrOne )
Мне нужно вернуть эти 4 объекта в виде одного списка, чтобы использовать его как часть графического представления онтологии.
2 ответа
Рассматривали ли вы (и отвергли) существующие решения, например: Йена?
Видимо, у вас есть какой-то цикл, проходящий через файл. Вот несколько идей:
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;
}
}
2) Когда встречается заголовок oneOf, создайте еще один маленький цикл для чтения его значений. Возможный недостаток может заключаться в том, что в результате вы получите два цикла, повторяющихся по файлу, и два вызова reader.readLine
, что может усложнить вещи или не может.
while(reader.ready()){
String line=reader.readLine();
if(line.contains("foo")){
...
}
else if (line.contains("owl:oneOf")){
Vector<String> oneOfList = new Vector<String>();
while(true){
String str = line.trim();
int a = str.indexOf("("); // -1 if not found, OK
int b = str.indexOf(")");
int c = (b>=0) ? b : str.length();
oneOfList.add(str.substring(a+1,c).trim());
if(b>=0) break;
line=reader.readLine();
}
storeOneOf(oneOfList);
}
}
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");
}
}