【问题标题】:bufferedreader won't move to the next linebufferedreader 不会移动到下一行
【发布时间】:2013-11-23 19:49:34
【问题描述】:

晚上好,

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

4,
Mo Farah,30,
Jessica Ennis,27,

我需要读取这些值并将它们放入变量中,这就是我尝试这样做的方式:

  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);

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

非常感谢

【问题讨论】:

  • 是的,您需要为每一行创建一个新的分词器(或使用新行重置现有的分词器),因为分词器包含与正在处理的行相关联的状态。
  • 哇,好浪费,能请教一下如何重置令牌吗?并将其添加为答案?谢谢
  • 不要使用 StringTokenizer -- 改用 String#split,正如 @Mark 建议的那样(尽管他的代码有一些问题)。
  • 实际上在 Java 中创建对象非常快。如果您来自 C++,这可能看起来像是一种浪费,但实际上它一点也不浪费。该语言旨在像这样使用。刚看了java doc,没有reset功能,新建一个tokenizer就好了。

标签: java bufferedreader stringtokenizer


【解决方案1】:

让我们看看发生了什么

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

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

       StringTokenizer st = new StringTokenizer(nextline,",");

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

       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???

为什么?

因为st 被用于解析"4," 行。在解析行之后分配nextline 不会更新st 的内部状态(这是不可能实现的)。它根本行不通。所以如果你在这里调用st.nextToken(),你会得到NoSuchElementException,就像你说的那样。因为您已经从st 中读取了"4" 并且没有留下任何令牌。

如果你想使用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.

下面将返回下一行的第一个标记"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);

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

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

【讨论】:

    【解决方案2】:

    如果我认为 csv 中的模式总是相同的......:

      while(nextline != null){ 
    
          String[] lecture = reader.readLine().split(",");
    
           if(lecture.lenght()>0){
                      System.out.println("Name: " + lecture[0]);
                   int age = Integer.parseInt(lecture[1]);//you need to int?
    
                      System.out.println(lecture[1]);
            }
                  else
                      System.out.println("Name: " + lecture[0]);
        }
    

    希望这会有所帮助...

    【讨论】:

      猜你喜欢
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      • 2021-06-28
      • 1970-01-01
      • 2020-06-01
      • 2018-07-02
      • 1970-01-01
      相关资源
      最近更新 更多