声明:
这里描述的解析问题非常简单。这个问题不仅仅是要求一种方法来实现解析。 - 这几乎是直截了当的 - 相反,它要求一种优雅的方式。这种优雅的方式可能是不首先按行读取然后自己解析每一行的方式,因为这显然不是必需的。但是,这种优雅的方式是否可以随时使用标准类?
问题:
我必须在java中解析以下形式的文本(这些记录不止这些记录;记录可以比这些示例更多行):
5
Dominik 3
Markus 3 2
Reiner 1 2
Samantha 4
Thomas 3
4
Babette 1 4
Diana 3 4
Magan 2
Thomas 2 4
第一个数字n是紧随其后的记录中的行数。每个记录由一个名称组成,然后是0到n个整数。
我认为使用java.util.Scanner
是一种自然的选择,但是当使用hasNextInt()
和hasNext()
来判断一条线是否已启动时,它会导致肮脏,我可以' t区分读取的数字是否是下一条记录的标题,或者它是前一条记录的姓氏后面的最后一个数字。上面的例子:
...
Thomas 3
4
...
在此,我不知道如何判断3
和4
是标题还是属于Thomas
的当前行。
当然我可以先逐行阅读,将它们放入另一个Scanner
,然后再次阅读它们,但这会有效地解析整个数据两次,这看起来很难看。还有更好的方法吗?
我需要一些标志,告诉我在最后一个分隔符跳过操作期间是否遇到换行符。
答案 0 :(得分:2)
您可以阅读行尾,而不是阅读单独的扫描仪,并使用String.split
,如下所示:
while (scanner.hasNextInt()) {
int count = scanner.nextInt();
for (int i = 0 ; i != count ; i++) {
if (!scanner.hasNext()) throw new IllegalStateException("expected a name");
String name = scanner.next();
List<Integer> numbers = new ArrayList<Integer>();
for (String numStr : scanner.readLine().split(" ")) {
numbers.add(Integer.parseInt(numStr));
}
... // Do something with name and numbers
}
}
这种方法避免了在读取名称后通过调用int
来检测行上最后一个readLine()
与下一行第一个整数之间的差异的必要性。线。
答案 1 :(得分:2)
使用FileReader
和BufferedReader
阅读文件,然后开始检查:
outer loop -->while readLine is not null
if line matches //d+ --> read value of number and put it into count
from 0 to count do what you want to do // inner loop
答案 2 :(得分:0)
File file = new File("records.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
/* Read file one line at a time */
while((line = reader.readLine()) != null){
int noOfRecords = Integer.parseInt(line);
/* read the next n lines in a loop */
while(noOfRecords != 0){
line = reader.readLine();
String[] tokens = line.split(" ");
noOfRecords--;
// do what you need to do with names and numbers
}
}
这里我们一次只读一行,所以我们第一次读一行时它将是一个int(称之为n),从那里读取一些内部的下一行n
行环。一旦它完成了这个内部循环,它就会出现在外面,下次你读到一行时,它肯定是另一个int或EOF。这样你就不必处理整数解析异常,我们只会读取所有行一次:)