Whotookthisname
Whotookthisname

Reputation: 3

IndexOutOfRangeException when trying to create an Object from a text file in C#

I'm currently in the middle of trying to take a '|' delimited text file and create objects from the data contained within. Example:

Name|Address|City|State|Zip|Birthday|ID|Etc.
Name2|Address2|City2|State2|Zip2|Birthday2|ID2|Etc.

The newly created object, is then added to a list of said objects and the program moves to the next line of the file by way of a while loop using .Peek() (to make sure I don't go past the end of the file).

However, when it gets to creating the second object (more specifically, the second field of the second object), it throws an Index Out Of Range Exception, and I can't for the life of me figure out why. Thank you whomever might read this!

    StreamReader textIn = new StreamReader(new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read));

        List<Student> students = new List<Student>();

        while (textIn.Peek() != -1)
        {
            string row = textIn.ReadLine();
            MessageBox.Show(row);
            string [] fields = row.Split('|');
            Student temp = new Student();

            try
            {
                temp.name = fields[0];
                temp.address = fields[1];
                temp.city = fields[2];
                temp.state = fields[3];
                temp.zipCode = Convert.ToInt32(fields[4]);
                temp.birthdate = fields[5];
                temp.studentID = Convert.ToInt32(fields[6]);
                temp.sGPA = Convert.ToDouble(fields[7]);
            }
            catch
            {
                MessageBox.Show("IndexOutOfRangeException caught");
            }

            students.Add(temp);
        }

        textIn.Close();

Upvotes: 0

Views: 1447

Answers (4)

Adil
Adil

Reputation: 148120

In the given data if you have atleast eight columns for every row, you wont be getting index of of range exception but parsing of item at 4, 6, 7 would fail as they are not numbers and converting the non number values to int and double raises the exception.

temp.zipCode = Convert.ToInt32(fields[4]); 
temp.studentID = Convert.ToInt32(fields[6]);
temp.sGPA = Convert.ToDouble(fields[7]);

You need to change the catch block to know the reason for exception

}
catch(Exception ex)
{
    MessageBox.Show(ex.Message);
}

Upvotes: 0

sa_ddam213
sa_ddam213

Reputation: 43596

Maybe ReadAllLines will work a bit better if the data is on each line:

            List<Student> students = new List<Student>();
            using (FileStream textIn = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                foreach (string line in File.ReadAllLines(path))
                {
                    MessageBox.Show(line);
                    string[] fields = line.Split('|');
                    Student temp = new Student();
                    try
                    {
                        temp.name = fields[0];
                        temp.address = fields[1];
                        temp.city = fields[2];
                        temp.state = fields[3];
                        temp.zipCode = Convert.ToInt32(fields[4]);
                        temp.birthdate = fields[5];
                        temp.studentID = Convert.ToInt32(fields[6]);
                        temp.sGPA = Convert.ToDouble(fields[7]);
                    }
                    catch
                    {
                        MessageBox.Show(string.Format("IndexOutOfRangeException caught, Split Result:", string.Join(", ", fields.ToArray())));
                    }
                    students.Add(temp);
                }
            }

Upvotes: 0

horgh
horgh

Reputation: 18534

  1. Check if you have all 8 fieds in a line.
  2. Show a message if ther isn't.
  3. Get the actual exception and show its message to see the real problem description.
  4. Use Double.TryParse Method and Int32.TryParse Method to be sure all numeric values are valid
  5. Also use while (!textIn.EndOfStream) instead.

 try
 {
    int tempInt;
    double tempDouble;
    if (fields.Length = 8)//#1
    {
        temp.name = fields[0];
        temp.address = fields[1];
        temp.city = fields[2];
        temp.state = fields[3];
        if (!int.TryParse(fields[4], out tempInt))    //#4
            temp.zipCode = tempInt;
        else
        {
           //..invalid value in field
        }
        temp.birthdate = fields[5];
        if (!int.TryParse(fields[6], out tempInt))    //#4
            temp.studentID = tempInt;
        else
        {
           //..invalid value in field
        }
        if (!int.TryParse(fields[7], out tempDouble)) //#4
            temp.sGPA = tempDouble;
        else
        {
           //..invalid value in field
        }
    }
    else //#2
    {
        MessageBox.Show("Invalid number of fields");
    }
}
catch (Exception ex)   //#3
{
    MessageBox.Show(ex.Message);
}

Upvotes: 0

Habib
Habib

Reputation: 223257

First you can't ensure if its a IndexOutOfRange Exception with your current catch block.

catch
{
    MessageBox.Show("IndexOutOfRangeException caught");
}

It can be anything, may be exception during parsing to double. You may modify your catch block to:

catch(IndexOutOfRangeException ex)
{
    MessageBox.Show(ex.Message);
}

Also if you are going to access fields[7] then its better if you can check against the length of array to ensure that you got atleast 8 elements in your array.

 if(fileds.Length >=8)
       {
        temp.name = fields[0];
        ....

To catch FormatException which can occur during double parsing you may add an extra catch block for:

catch (FormatException ex)
{
    MessageBox.Show(ex.Message);
}

Upvotes: 1

Related Questions