bufferedreader 不会移动到下一行

use*_*644 2 java bufferedreader stringtokenizer

晚上好,

我需要从文件中读取一些行,该文件是 csv,文件的结构如下:

4,
Mo Farah,30,
Jessica Ennis,27,
Run Code Online (Sandbox Code Playgroud)

我需要读取这些值并将它们放入变量中,这就是我尝试执行此操作的方式:

  while(nextline != null){
           StringTokenizer st = new StringTokenizer(nextline,",");
           int size = Integer.parseInt(st.nextToken());
           System.out.println(size);

           nextline = reader.readLine();

           StringTokenizer st2 = new StringTokenizer(nextline, ","); //why???


           String name = st2.nextToken();
           System.out.println(name);
           int age = Integer.parseInt(st2.nextToken());

           System.out.println(age);
Run Code Online (Sandbox Code Playgroud)

第一个 int (4) 读取得很好,但是如果我想移动到下一行,它会抛出 noSuchElementException,所以我必须在“//why???”旁边写下这一行 为了移至下一行,每次我想移至下一行时,我真的必须实例化一个新的分词器吗?或者有更好的方法吗?

非常感谢

Emi*_* L. 5

让我们看看发生了什么

nextline = reader.readLine(); // I'm assuming you have this here
while(nextline != null){
Run Code Online (Sandbox Code Playgroud)

以下代码将解析该行"4,"并将其拆分为由其分隔的标记,其中,将包含 1 个标记"4"::

       StringTokenizer st = new StringTokenizer(nextline,",");
Run Code Online (Sandbox Code Playgroud)

以下操作将会成功,但您确实应该st.hasMoreTokens()在执行此操作之前检查是否返回 true。它将消耗"4"现在st不再包含令牌的令牌:

       int size = Integer.parseInt(st.nextToken());
       System.out.println(size);

       // We read the next line into "nextline", this is okay but not pretty.
       // Also you need to check that nextline is not `null` here.
       nextline = reader.readLine();

       StringTokenizer st2 = new StringTokenizer(nextline, ","); //why???
Run Code Online (Sandbox Code Playgroud)

为什么?

因为st是为了解析该行"4,"。在解析nextline该行后进行分配不会更新其内部状态st(这是不可能实现的)。它根本不是那样工作的。所以如果你打电话st.nextToken()到这里,你就会得到NoSuchElementException你所说的。因为您已经阅读了来自"4"并且st没有剩余的令牌。

如果您想使用 ,以下是正确的做法StringTokenizer,它将导致该行"Mo Farah,30,"被解析为标记:"Mo Farah""30"

       st = new StringTokenizer(nextline, ","); // Just parse the new line.
       // You can reuse the old st variable as it is now depleted.
Run Code Online (Sandbox Code Playgroud)

现在,以下代码将返回下一行的第一个标记,即"Mo Farah"。尽管如此,您确实应该st.hasMoreTokens()首先检查并给出合理的错误消息:

       String name = st.nextToken(); // Change from st2 to st
       System.out.println(name);
       int age = Integer.parseInt(st.nextToken()); // Ditto

       System.out.println(age);
Run Code Online (Sandbox Code Playgroud)

所以简短的答案是,是的,如果你想使用StringTokenizer你必须StringTokenizer为每一行创建一个新的。如果您不关心上面的行结尾,您可以读取所有行并将它们连接起来,然后再将其全部传递给StringTokenizer.

但最简单的方法就是使用 String tokens[] = newline.split(","); 正如马克在回答中所做的那样。