简体   繁体   中英

C# StreamReader failing to read lines

I am creating a banking program and I want to be able to read my text file of accounts and add them to a list. My problem is, it only reads 1 line and after that, it will get an error saying the line is null, but it shouldn't be because the second like should be the age.

I want it to continuously go through the accounts adding the data to the List, each account is separated by a blank line.

Code:

 StreamReader FileToRead = new StreamReader(@"C:\Users\...\Accounts.txt");
        Account NewAccount = new Account();

        string line;

        do
        {
            NewAccount.Name = FileToRead.ReadLine();
            NewAccount.Age = int.Parse(FileToRead.ReadLine());
            NewAccount.Balance = int.Parse(FileToRead.ReadLine());
            NewAccount.Address.Country = FileToRead.ReadLine();
            NewAccount.Address.City = FileToRead.ReadLine();
            NewAccount.Address.FirstLine = FileToRead.ReadLine();
            NewAccount.Address.SecondLine = FileToRead.ReadLine();
            NewAccount.Address.PostCode = FileToRead.ReadLine();
            NewAccount.AccountNumber = int.Parse(FileToRead.ReadLine());
            Accounts.Add(NewAccount);
        } while ((line = FileToRead.ReadLine()) != null);

Text file: http://pastebin.com/raw.php?i=1r9TEUPx

Tried with your file and the code fails at the second loop not the first one.
This because the "blankline" at the end triggers a second loop but then there is no more data to read.

If you are sure that every 'record' is separated by a blank line then you could simply add another read at the end of the loop

    do
    {
        NewAccount = new Account();

        NewAccount.Name = FileToRead.ReadLine();
        NewAccount.Age = int.Parse(FileToRead.ReadLine());
        NewAccount.Balance = int.Parse(FileToRead.ReadLine());
        NewAccount.Address.Country = FileToRead.ReadLine();
        NewAccount.Address.City = FileToRead.ReadLine();
        NewAccount.Address.FirstLine = FileToRead.ReadLine();
        NewAccount.Address.SecondLine = FileToRead.ReadLine();
        NewAccount.Address.PostCode = FileToRead.ReadLine();
        NewAccount.AccountNumber = int.Parse(FileToRead.ReadLine());

        FileToRead.ReadLine(); // here to absorb the empty line between 'records'

        Accounts.Add(NewAccount);
    } while ((line = FileToRead.ReadLine()) != null);

Now when you reach the end-of-file the while loop exits correctly.....

EDIT: Seeing the answer from Eric -- Added the correct initialization of a new Account for every loop

Well, the only real error I can see offhand is that you're not creating a new instance of Account - so what you'll be doing is changing the values on a single account and readding it to the list - you'll only end up with the last account in the file stored. You need to create a new Account for each iteration of the loop.

Another way to do it:

string[] lines = System.IO.File.ReadAllLines(@"C:\Users\...\Accounts.txt");

         if (lines != null && lines.Length > 0)
         { 
         Account NewAccount = new Account();
         NewAccount.Name = lines[0].ToString();
         NewAccount.Age = lines[1].ToString();
         NewAccount.Balance = lines[2].ToString();
         NewAccount.Address.Country = lines[3].ToString();
         NewAccount.Address.City = lines[4].ToString();
         NewAccount.Address.FirstLine = lines[5].ToString();
         NewAccount.Address.SecondLine = lines[6].ToString();
         NewAccount.Address.PostCode = lines[7].ToString();
         NewAccount.AccountNumber = lines[8].ToString();
         Accounts.Add(NewAccount);
         }

If you have such problems with the Streamreader, consider to use File.ReadAllLines instead:

var lines = File.ReadAllLines(path);
var NewAccount = new Account();
NewAccount.Name = lines.First();
NewAccount.Age = int.Parse(lines.ElementAt(1));
NewAccount.Balance = int.Parse(lines.ElementAt(2));
NewAccount.Address.Country = lines.ElementAt(3);
NewAccount.Address.City = lines.ElementAt(4);
NewAccount.Address.FirstLine = lines.ElementAt(5);
NewAccount.Address.SecondLine = lines.ElementAt(6);
NewAccount.Address.PostCode = lines.ElementAt(7);
NewAccount.AccountNumber = int.Parse(lines.ElementAt(8));

If your contains valid data your code probably throws exception on:

NewAccount.Address.Country = FileToRead.ReadLine();

It looks like you have some kind of class for address. You have to instantiate this property in Account constructor or in loop:

do
        {
            ...
            NewAccount.Balance = int.Parse(FileToRead.ReadLine());
            NewAccount.Address = new Account.AddressClass();
            NewAccount.Address.Country = FileToRead.ReadLine();
            ...
        } while ((line = FileToRead.ReadLine()) != null);

I also assumed you previously instantiated other variables like

Account NewAccount = new Account();
List<Account> Accounts = new List<Account>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM