简体   繁体   中英

C# Filling a 2D array with objects from a txt file at specific positions

Im trying to fill a 2D array with a txt file from my computer.

I have tried doing this in two different ways but i have not gotten either to work.

  1. Save objects position number in the file using the following code.

     for (int row = 0; row < 100; row++) { for (int col = 0; col < 2; col++) { if (cpp[row, col] == null) { break; } else { if (cpp[row, col] == null) continue; save.WriteLine(string.Format("{0}, {1}, {2}, {3}", row + 1, cpp[row, col].RegNumber, cpp[row, col].VehicleTypes, cpp[row, col].TimeOfArrival)); } } }

Second way i have tried is to save the file with the empty lines aswell.

 foreach (var temp in cpp)
            {
                if (temp == null) save.WriteLine("");
                if (temp == null) continue;
               save.WriteLine("{{0},{1},{2}", temp.RegNumber, temp.VehicleTypes, temp.TimeOfArrival);
            }

I have gotten nowhere with the load function and i would appreciate any help i can get with this. I need to load the file in to my 2D array and the objects have to be assigned to the same position it was before.

The only code i have for the load function is this.

string[] lines = File.ReadAllLines("CarParkPrague.txt");
            var vehicles = new List<Vehicle>();
            {
                foreach (var line in lines)
                {
                    var values = line.Split(",");
                    Enum.TryParse(values[1], out VehicleType type);
                    var time = DateTime.Parse(values[2]);
                    vehicles.Add(new Vehicle(values[0], type, time)); 
                    
                }
            }

Text file line example = AAA111,CAR,2020-10-11 14:19:04 Or with the position saved = 1,AAA111,CAR,2020-10-11 14:19:04 Can be either, which ever is easiest.

This is a test method that works but it saves the vehicles on first best available spot in the array so its not quite right. The text file is in this case saved without a position number. And looks like the first example above.

static void LoadTestFile() //Loads the array using the test file which is filled with examples.
    {
        string[] lines = File.ReadAllLines("testfile.txt");
        var vehicles = new List<Vehicle>();

        foreach (var line in lines)
        {
            var values = line.Split(",");
            Enum.TryParse(values[1], out VehicleType type);
            var time = DateTime.Parse(values[2]);
            vehicles.Add(new Vehicle(values[0], type, time));
        }

        int counter = 0;
        for (int i = 0; i < 100; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                if (counter >= vehicles.Count)
                    break;

                if (cpp[i, 0] != null)
                {
                    if (cpp[i, 0].VehicleTypes == VehicleType.CAR)
                    {
                        continue;
                    }
                }

                if (vehicles[counter].VehicleTypes == VehicleType.CAR)
                {
                    cpp[i, j] = vehicles[counter++];
                }
                else
                {
                    cpp[i, j] = vehicles[counter++];
                }
            }
        }

Your loading function will crash if you have empty lines, so I can't quite believe it works to read a file with blank lines on. The big problem with it though is that it doesn't do anything if it encounters a blank line when really it should be putting a blank (null) vehicle at that position in the list

Save blank lines if the vehicle is null, and also save dates in a fixed format:

        foreach (var temp in cpp)
        {
            if (temp == null) 
                save.WriteLine();
            else
                save.WriteLine("{{0},{1},{2}", temp.RegNumber, temp.VehicleTypes, temp.TimeOfArrival.ToString("yyyyMMddHHmmss"));
        }

Load, catering for blank lines by putting no vehicle (null) in that position:

        string[] lines = File.ReadAllLines("CarParkPrague.txt");
        var vehicles = new List<Vehicle>();
        
        foreach (var line in lines)
        {
            if(string.IsNullOrWhiteSpace(line))
            { 
                vehicles.Add(null);
                continue;
            }
            var values = line.Split(",");
            Enum.TryParse(values[1], out VehicleType type); //should really test this with an if
            var time = DateTime.ParseExact(values[2], "yyyyMMddHHmmss", null);
            vehicles.Add(new Vehicle(values[0], type, time)); 
                
        }
    }

Hopefully you can see how your "if the parking space is empty the vehicle is null and this becomes a blank line during save" is translated back upon load to "if the line is blank then the space is marked as empty by putting a null vehicle there"

Edit; as you seem to have a fixed number of parking spaces and are using null to represent emptiness, having a collection like a List, which dynamically sizes to fit the contents is perhaps not ideal. Switch to using an array that represents the size of the car park:

    string[] lines = File.ReadAllLines("CarParkPrague.txt");
    var vehicles = new Vehicle[100];
    
    for (int i = 0; i < lines.Length && i < vehicles.Length; i++)
    {
        var line = lines[i];

        if(string.IsNullOrWhiteSpace(line))
            continue;
        
        var values = line.Split(",");
        Enum.TryParse(values[1], out VehicleType type); //should really test this with an if
        var time = DateTime.ParseExact(values[2], "yyyyMMddHHmmss", null);
        vehicles[i] = new Vehicle(values[0], type, time); 
            
    }
}

Don't forget that the vehicles in the load method should be assigned to the same variable that cpp in the save method represents. Really, you ought to use the same class wide variable in both methods

Let's start with something that's entirely trivial - mirror the save and load methods. The only thing you really need to add is the dimensions of the array:

var rowCount = cpp.GetLength(0);
var colCount = cpp.GetLength(1);

save.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0},{1}", rowCount, colCount));
for (var row = 0; row < rowCount; row++)
{
  for (var col = 0; col < colCount; col++)
  {
    if (cpp[row, col] == null) save.WriteLine();
    else save.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", cpp[row, col].RegNumber, cpp[row, col].VehicleTypes, cpp[row, col].TimeOfArrival));
  }
}

To read this very straight-forward file format, do the same thing in reverse:

using (var sr = new StreamReader("CarParkPrague.txt"))
{
  var dimensions = sr.ReadLine()?.Split(',');

  if (dimensions == null 
      || !int.TryParse(dimensions[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var rowCount) 
      || !int.TryParse(dimensions[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var colCount)
     )
    throw new Exception("Invalid dimensions.");

  var cpp = new Vehicle[rowCount, colCount];

  for (var row = 0; row < rowCount; row++)
  {
    for (var col = 0; col < colCount; col++)
    {
      if (!(sr.ReadLine() is {} line) throw new Exception("Unexpected end of file.");
      if (string.IsNullOrWhitespace(line)) continue;

      var values = line.Split(",");
      if (!Enum.TryParse(values[1], out var vehicleType)) throw new Exception($"Unexpected vehicle type '{values[1]}'.");
      if (!DateTime.TryParse(values[2], CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTime) throw new Exception($"Invalid time '{values[2]}'.");

      cpp[row, col] = new Vehicle(values[0], type, time); 
    }
  }
}

There's plenty of ways to optimize this, but there's little reason to bother if the resulting file is just a few kilobytes (or even tens of kilobytes).

Thanks for all the help. This is a solution that works for my project. Save file and load in to the 2d array.

 static void SaveFile() //Saves the current array using streamwriter.
    {
        Console.Clear();
        StreamWriter save = new StreamWriter("CarParkPrague.txt");
        using (save)
        {
     
            foreach (var temp in cpp)
            {
                if (temp == null) save.WriteLine();
                else
                save.WriteLine("{0},{1},{2}", temp.RegNumber, temp.VehicleTypes, temp.TimeOfArrival);
            }
        }
        Console.WriteLine("File saved succesfully");
        Console.WriteLine("----------------------------------------------------------------");
    }


static void LoadFile() //Loads the array using the saved file.
    {
        try
        {
            string[] lines = File.ReadAllLines("CarParkPrague.txt");
            var vehicles = new List<Vehicle>();
            {
                foreach (var line in lines)
                {
                    if (string.IsNullOrWhiteSpace(line))
                    {
                        vehicles.Add(null);
                        continue;
                    }
                    var values = line.Split(",");
                    Enum.TryParse(values[1], out VehicleType type);
                    var time = DateTime.Parse(values[2]);
                    vehicles.Add(new Vehicle(values[0], type, time)); 
                    
                }
            }
            int counter = 0;
            for (int i = 0; i < 100; i++)
            {
                for (int j = 0; j < 2; j++)
                {

                    if (vehicles[counter] == null)
                    {
                        cpp[i, j] = vehicles[counter++];
                    }
                   else if (vehicles[counter] != null)
                    {
                        cpp[i, j] = vehicles[counter++];
                    }
                }
            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine(ex);
            Console.WriteLine("File could not be found. Please make sure there is a file named (CarParkPrague.txt) in your folder.");
        }
        Console.Clear();
        Console.WriteLine("File have been loaded succesfully");
        Console.WriteLine("----------------------------------------------------------------");
    }

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