在java中解析这个文本的优雅方法是什么?

时间:2015-02-04 15:18:20

标签: java java.util.scanner

声明
这里描述的解析问题非常简单。这个问题不仅仅是要求一种方法来实现解析。 - 这几乎是直截了当的 - 相反,它要求一种优雅的方式。这种优雅的方式可能是首先按行读取然后自己解析每一行的方式,因为这显然不是必需的。但是,这种优雅的方式是否可以随时使用标准类?

问题:
我必须在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
...

在此,我不知道如何判断34是标题还是属于Thomas的当前行。

当然我可以先逐行阅读,将它们放入另一个Scanner,然后再次阅读它们,但这会有效地解析整个数据两次,这看起来很难看。还有更好的方法吗?

我需要一些标志,告诉我在最后一个分隔符跳过操作期间是否遇到换行符。

3 个答案:

答案 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)

使用FileReaderBufferedReader阅读文件,然后开始检查:

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。这样你就不必处理整数解析异常,我们只会读取所有行一次:)