【问题标题】:Java encountering runtime errors while trying to read text fileJava 在尝试读取文本文件时遇到运行时错误
【发布时间】:2026-01-24 16:45:01
【问题描述】:

我目前正在尝试按顺序编写一个 Java 作业;

  1. 读取预写文本文件的每一行
  2. 将每一行变成一个字符串
  3. 把每一行的每一部分都变成自己独立的字符串/int/double
  4. 将这些变量分配到一个类的对象(它是对象数组的一部分)中,该类也是我作为此分配的一部分创建的
  5. 使用类的方法之一打印对象的每个变量

但是,我反复遇到运行时问题,我收到此错误消息;

线程“main”中的异常 java.util.NoSuchElementException 在 java.util.Scanner.throwFor(Scanner.java:862) 在 java.util.Scanner.next(Scanner.java:1371) 在 Lab2.main(Lab2.java:27)

这让我相信我可能读错了文本文件。但是,无论我做什么,我似乎都无法正确读取它。它应该读取名字、姓氏、地址的三个独立组成部分(它连接成一个字符串)、城市、州、邮政编码(作为整数)、电话号码(作为字符串)和一个美元金额(作为双倍)。

我认为问题可能来自城市名称,因为其中一些城市名称之间有空格。我以为我已经通过将读取每个单独字符串的扫描器的分隔符设置为选项卡(这是所有其他元素的分隔符)来解决这个问题,但这要么不起作用(因此试图将状态名称转换为整数通过 Integer.parseInt() 静态方法)或者不是问题。正如我所说,我没有想法,并且非常感谢任何可以在这里帮助我的人!

我将在下面列出代码。首先是主文件;

public class Lab2
{ 
    public static void main(String[] args) throws IOException
    { String FirstName, LastName, Address1, Address2, Address3, AddressFull, City, State, Phone, ZipString, DonString, line = "blank";
      int Zip;
      double Donation;

      Scanner fileScan = new Scanner(new File("Lab2.txt")), lineScan = new Scanner(line);
      lineScan.useDelimiter("\t");

      PersonStats[] Donators = new PersonStats[25];

      for (int i = 0; i < Donators.length; i++)
      { line = fileScan.nextLine();

        FirstName = lineScan.next();
        LastName = lineScan.next();

        Address1 = lineScan.next();
        Address2 = lineScan.next();
        Address3 = lineScan.next();
        AddressFull = Address1 + " " + Address2 + " " + Address3;

        City = lineScan.next();
        State = lineScan.next();

        ZipString = lineScan.next();
        Zip = Integer.parseInt(ZipString);

        Phone = lineScan.next();

        DonString = lineScan.next();
        Donation = Double.parseDouble(DonString);

        Donators[i] = new PersonStats(FirstName, LastName, AddressFull, City, State, Zip, Phone, Donation);
        Donators[i].PrintOut();
      }

    }
}

接下来是我为作业编写的课程文件;

public class PersonStats
{ private String FirstName, LastName, Address, City, State, Phone;
private int Zip;
private double Donation;

public PersonStats(String first, String last, String area, String town, String feifdom, int postcode, String telegraph, double given)
{ FirstName = first;
  LastName = last;
  Address = area;
  City = town;
  State = feifdom;
  Zip = postcode;
  Phone = telegraph;
  Donation = given;
}

public void PrintOut()
{ System.out.println(FirstName + " " + LastName);
  System.out.println(Address);
  System.out.println(City + ", " + State + " " + Zip + "\n");
  System.out.println(Phone + " " + Donation);
}

}

最后是程序应该读取的文本文件(可能有点难以阅读,记住除了城市名称中的每个空格实际上是一个选项卡);

Rick    James   8276    Carlos  Ave Las Vegas   NV  87126   5553451567  23.95
John    Gibson  9127    Oak Dr  Corvallis   OR  97330   5552812313  156.78
Ron Wills   1155    Ivy Pl  Atlantic    Ga  37339   5552123145  189.56
Rita    Jones   1259    Chase   Ave Las Vegas   NV  87126   5554445671  2145.60
Jason   Knight  7154    Pine    Dr  Gresjam     OR  97380   5558124545  3157.44
Clara   Swanson 1944    Main    Pl  Springfield OR  97339   5552123144  212.99
Robert  Peck    1866    First   Ave Las Vegas   NV  87126   5553455425  250.00
Dora    Garcia  2179    Fir Dr  Corvallis   OR  97330   5552812919  350.00
Peter   Keck    1465    Circle  Pl  Gold Beach  OR  97339   5552123256  2150.00
Stuart  Smith   2387    Sweek   Ave Las Vegas   NV  87126   5553455489  650.99
Tyler   Wild    1313    Spooky  Ln  Corvallis   OR  97330   5552813213  587.45
Laretta Peters  2224    Chase   Pl  Monmouth    OR  97361   5552124465  123.45
Kristi  Emry    3465    Cerrito Ave Las Vegas   NV  87126   5553455567  3212.65
Kelli   Gard    1894    Elm Dr  Corvallis   OR  97330   5552816678  51.00
Jacob   Andrews 8159    Rose    Ct  Mill City   OR  97322   5552127879  64.00
Ryan    Perkins 7546    Prince  Ave Las Vegas   NV  87126   5553451989  13.00
Joshua  Gilbert 9278    Monroe  Dr  Corvallis   OR  97330   5552832656  95.00
Miles   Crain   4578    Chester Dr  Corvallis   OR  97331   5552345678  1544.00
Butch   Cassidy 5498    Sutton  Pl  Gresham     OR  97380   5416565797  1798.56
Perry   Winkle  8185    Shaver  Ave Las Vegas   NV  87126   5553812346  195.66
Loni    Day 4598    Holmen  Dr  Corvallis   OR  97330   5555289741  1878.50
Nikita  Benson  1787    Grant   Pl  Portland    OR  97321   5553569898  1500.00
Rusty   Krouger 8829    Simeon  Ave Las Vegas   NV  87126   5555677847  2100.00
Wally   Wallace 2898    Wilson  Blvd    Jackson Center  OH  23466   5552222222  2222.22
Joe     Jones   1212    Water   St  Millersburg OR  97366   5555555555  55.55

再次感谢,如果有人可以帮助我解决这个问题,您的建议可能会挽救生命!...或者至少是这个实验室的分数:S

【问题讨论】:

  • 检查*.com/questions/13102045/…。顺便说一句,你为什么不使用FileReader + BufferedReader
  • 在执行相应的next~:hasNextLine,hasNext之前存在许多检查。
  • 您的示例文本文件实际上并未由制表符分隔。我正在使用 5 人详细记录文本文件的答案中为您发布工作代码
  • @Aniket 在实际文件中它们是,但是当它复制到选项卡上时变成了空格。我不知道为什么会这样。
  • @Scopicus 是的,当我在这里发布文件时,文件值也发生了变化。你可能想看看我的回答。

标签: java


【解决方案1】:

这里有个提示:使用 Scanner 时,在调用 next 方法之前使用 hasNextXXX 方法来检查元素是否存在

https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html

No Such Element Exception?

【讨论】:

    【解决方案2】:

    好的,就到这里

    import java.io.IOException; 
    import java.io.*;
    import java.util.Scanner;
    public class Lab2
    { 
        public static void main(String[] args) throws IOException
        { String FirstName, LastName, Address1, Address2, Address3, AddressFull, City, State, Phone, ZipString, DonString, line = "blank";
          int Zip;
          double Donation;
    
          Scanner fileScan = new Scanner(new File("F:/test.txt")).useDelimiter("\n");
    
          PersonStats[] Donators = new PersonStats[5];
          String tempVal="";
          int i = 0;
          while(fileScan.hasNext())
          {
            tempVal = fileScan.next();  //Storing person records one at a time in the string line by line
            String tempArr[] = tempVal.split("\t"); //Splitting each person record string by tab and storing it in a String array
    
                FirstName = tempArr[0];
                LastName = tempArr[1];
    
                Address1 = tempArr[2];
                Address2 = tempArr[3];
                Address3 = tempArr[4];
                AddressFull = Address1 + " " + Address2 + " " + Address3;
    
                City = tempArr[5];
                State = tempArr[6];
    
                ZipString = tempArr[7];
                Zip = Integer.parseInt(ZipString);
    
                Phone = tempArr[8];
    
                DonString = tempArr[9];
                Donation = Double.parseDouble(DonString);
                Donators[i] = new PersonStats(FirstName, LastName, AddressFull, City, State, Zip, Phone, Donation);
                Donators[i].PrintOut();
                i++;
          }  
        }
    }
    

    首先,我想指出你的变量名应该以小写开头。我没有在代码中编辑它们,因为它们在很多地方都使用过。养成声明String firstName而不是String FirstName的习惯

    对于代码,在您的代码中,您使用了 "\t" 分隔符,我将其替换为 "\n",因为在文本文件中,每一行都包含完整的 Person 详细信息。如果第一个人的捐款和第二个人的名字用相同的分隔符分隔,但用“\n”分隔,则可以使用"\t"

    所以现在Scanner fileScan 将逐行读取我将存储在String tempVal 中的文件,while(fileScan.hasNext()) 确保只要有要读取的行,扫描器就会继续读取。

    现在,每一行都有不同的信息,由"\t" 分隔。所以我用tempVal.split("\t") 将它们分开。此外,使用了计数器 int i 并删除了 for 循环。我想其余的代码都很基本,和你的没有太大区别。

    **编辑****

    这是输出

    Rick James
    8276 Carlos Ave
    Las Vegas, NV 87126
    
    5553451567 23.95
    John Gibson
    9127 Oak Dr
    Corvallis, OR 97330
    
    5552812313 156.78
    Ron Wills
    1155 Ivy Pl
    Atlantic, Ga 37339
    
    5552123145 189.56
    Rita Jones
    1259 Chase Ave
    Las Vegas, NV 87126
    
    5554445671 2145.6
    Jason Knight
    7154 Pine Dr
    Gresjam, OR 97380
    
    5558124545 3157.44
    

    这是我使用的示例 text.file。

    Rick    James   8276    Carlos  Ave Las Vegas   NV  87126   5553451567  23.95
    John    Gibson  9127    Oak Dr  Corvallis   OR  97330   5552812313  156.78
    Ron Wills   1155    Ivy Pl  Atlantic    Ga  37339   5552123145  189.56
    Rita    Jones   1259    Chase   Ave Las Vegas   NV  87126   5554445671  2145.60
    Jason   Knight  7154    Pine    Dr  Gresjam OR  97380   5558124545  3157.44
    

    【讨论】:

    • 您的修复工作完美!非常感谢您的建议。
    【解决方案3】:
     Scanner fileScan = new Scanner(new File("Lab2.txt"));
    
    
          //PersonStats[] Donators = new PersonStats[25];
    
          while(fileScan.hasNext()) {
    
    
             line = fileScan.nextLine();
    
            String parts[] = line.split("\t");        
    
            if(parts.length == 10) {
    
                FirstName = parts[0];
    
    
                ...
            }
    

    另外还有一些问题。 第一:字符串是不可变的。因此,您的 lineScanner 将使用空字符串创建。如果您稍后更改此字符串,则此扫描仪不会添加任何内容,因为您通过此步骤创建了一个新字符串。

    其次,您必须检查下一个元素。 (见我的 while 循环)

    要解析您的数据,将字符串分成几部分并使用它来填充您的类更容易。但是如果你想使用 Scanner 类,你必须在文件中的每一行创建一个实例。(在 while 循环中)

    【讨论】: