I have a text file filled with several lines of data, and I would like to split it into 5 different elements like so..

I am successfully reading in the data and putting it into an array. Now I would like to split each part of the text up into different lists so I can compare the data against one another.
I have currently managed to read in the first 4 elements of each line into their relevant lists but the 5th one is throwing me the error "System.IndexOutOfRangeException" which I can only assume is because the first line it reads in has no value for the 5th element?
So my question is, is there a way to populate null values when writing them to a number of lists?
I've tried manually assigning the size of the array and lists but I still get the same error.
Here is my code:
class Program { static void Main(string[] args) { // Reading in file containing data from BT Code Evaluation sheet (for testing purposes). // Each line gets stored into a string array, each element is one line of the data.txt file. //String[] lines = System.IO.File.ReadAllLines(@"C:\Users\Ad\Desktop\data.txt"); String[] lines = new String[5] {"monitorTime", "localTime", "actor", "action", "actor2"}; lines = System.IO.File.ReadAllLines(@"C:\Users\Ad\Desktop\data.txt"); char delimiter = ' '; List<String> monitorTime = new List<String>(); List<String> localTime = new List<String>(); List<String> actor = new List<String>(); List<String> action = new List<String>(); List<String> actor2 = new List<String>(); // Foreach loop displays the lines of text in the data file. foreach (String line in lines) { // Writes the data to the console. Console.WriteLine(line); String[] data = new String[5] { "monitorTime", "localTime", "actor", "action", "actor2" }; data = line.Split(delimiter); monitorTime.Add(data[0]); localTime.Add(data[1]); actor.Add(data[2]); action.Add(data[3]); actor2.Add(data[4]); } foreach (String time in monitorTime) { Console.WriteLine(time); } foreach (String time in localTime) { Console.WriteLine(time); } foreach (String name in actor) { Console.WriteLine(name); } foreach (String actions in action) { Console.WriteLine(actions); } foreach (String name in actor2) { if (name != null) { Console.WriteLine("UNKNOWN"); } else { Console.WriteLine(actor2); } } // Creates an empty line between the data and the following text. Console.WriteLine(""); // Displays message in console. Console.WriteLine("Press any key to analyse data and create report..."); Console.ReadKey(); } } 82 Answers
You need to check the bounds of you array before you try to add. If their aren't enough items you can add null instead.
For example:
actor2.Add(data.length > 4 ? data[4] : null) (Note: You could do the same type of check on the other items as well, unless you are positive that the last item is the only one that might be null)
This is using the ternary operator, but you could also use a simple if/else, but it'll be more verbose. It's equivalent to:
if (data.length > 4) { actor2.Add(data[4]); } else { actor2.Add(null); } This along with Console.WriteLine(name); instead of Console.WriteLine(actor2); should fix you immediate problem.
However, a much better design here would be to have a single list of objects with MonitorTime, LocalTime, Actor, Action and Actor2 properties. That way you don't ever have to worry that the 5 parallel arrays might get out of sync.
For example, create a class like this:
public class DataItem { public string MonitorTime { get; set; } public string LocalTime { get; set; } public string Actor { get; set; } public string Action { get; set; } public string Actor2 { get; set; } } Then instead of your 5 List<String>, you have one List<DataItem>:
List<DataItem> dataList = new List<DataItem>(); Then in your loop to populate it you'd do something like:
data = line.Split(delimiter); dataList.Add(new DataItem() { MonitorTime = data[0], LocalTime = data[1], Actor = data[2], Action = data[3], Actor2 = data.length > 4 ? data[4] : null }); Then you can access them later with something like:
foreach (var item in dataList) { Console.WriteLine(item.MonitorTime); //... } 5In your for each you should be checking to see if the index exists before populating the object.
foreach (String line in lines) { // Writes the data to the console. Console.WriteLine(line); String[] data = new String[5] { "monitorTime", "localTime", "actor", "action", "actor2" }; data = line.Split(delimiter); monitorTime.Add(data[0]); localTime.Add(data[1]); actor.Add(data[2]); action.Add(data[3]); if (data.Length > 4) { actor2.Add(data[4]); } } There's better ways to do this but this is a simple solution for now.
1