kamir
kamir

Reputation: 3

How to read data in file and save line to two-dimensional table

I want to read file text. Save only numbers and the final letter to two-dimensional array. Line of the file (example):

[4; 5)|[1; 1,5)|B

    static void read()
    {
        string[] lines = System.IO.File.ReadAllLines(@"C:\learning.txt");

        int n = lines.Length; 


        string[ , ] tab = new string[n, 5];  

        int i = 0;


        foreach (string line in lines)
        {

            Char[] znaki = { '[', ';', ')', '|', ' ' };
            string[] names = line.Split(znaki);


           // Console.WriteLine(names[1]+"\t"+names[3] + "\t" + names[6] + "\t" + names[8] + "\t" + names[10]);


            tab[i, 0] = names[1];
            tab[i, 1] = names[3];
            tab[i, 2] = names[6];
            tab[i, 3] = names[8];
            tab[i, 4] = names[10];

            i++;

        }

        Console.ReadKey();
    }

I would like to have data separated in 5 columns and n lines (the file may be expanded in the future with new lines) but it always saves only the first line.Thanks

Upvotes: 0

Views: 78

Answers (2)

pwilcox
pwilcox

Reputation: 5753

I am running your code and not seeing that it only saves one line as you experience. Something else is going on in that regard.

KreLou is absolutely right in pressing you to put the lines into a class instance. Otherwise, you loose type-safety, meaning many errors will arise at run-time as opposed to compile-time or design-time. It also lets users of your code (including yourself, later in time) understand the purpose of the object much more easily.

Again KreLou is right in that StreamReader is better than File.ReadAllLines, because the latter loads all lines into memory at once instead of just loading one line at a time.

However, I'm posting my own version for the following benefits:

  • File.ReadLines() has similar benefits to StreamReader for this use, and requires a little less code.
  • The label you put for variable of delimiters is confusing
  • The RemoveEmptyEntries Split takes away the sparseness of your split output
  • Yield returning from the read function, again to save code and it has it's other benefits.
  • And I overrode the ToString() method of the class so you can still see it's output in the console.
  • I put the string split logic into the class constructor. This is not necessarily better than keeping it in the read() function, but it gives you a chance to see how class constructors work.
  • I also just wanted to stress the reasonings I gave above.

Here's the class to hold each line of your file:

public class learnLine {

    static Char[] delimiters = { '[', ';', ')', '|', ' ' };

    public int num1 { get; set; }
    public int num2 { get; set; }
    public int num3 { get; set; }
    public int num4 { get; set; }
    public string letter { get; set; }  

    public learnLine (string line) {
        string[] parts = line.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
        num1 = Convert.ToInt32(parts[0]);
        num2 = Convert.ToInt32(parts[1]);
        num3 = Convert.ToInt32(parts[2]);
        num4 = Convert.ToInt32(parts[3].Substring(0,1)); // from your logic it seems like you only want the first?
        letter = parts[4];
    }

    public override string ToString () =>
        $"contents: {num1}|{num2}|{num3}|{num4}|{letter}";

}

Here's the function to read your lines:

IEnumerable<learnLine> read(string path) {

    foreach (var line in File.ReadLines(path)) {
        yield return new learnLine(line);
    }

}

And here's how to use your function to output the results to the console:

IEnumerable<learnLine> lines = read(@"C:\learning.txt");

foreach(var line in lines) {
    Console.WriteLine(line.ToString());
}

Upvotes: 0

KreLou
KreLou

Reputation: 125

Why not creating objects/dtos?

Create an object:

public class ElementDTO {
    public int Number1 {get; set}
    public int Number2 {get; set}
    public int Number3 {get; set}
    public int Number4 {get; set}
    public char InputChar {get; set}

}

And read the file via StreamReader:

List<ElementDTO> list = new List<ElementDTO>();
using (StreamReader sr = new StreamReader("/path/to/file"){
   string line;
   while((line = sr.ReadLine()) != null) {

   ...//here your split code

   ElementDTO element = new Element {
     Number1 = ...;
     Number2 = ...;
     Number3 = ...;
     Number4 = ...;
     InputChar = ....;
   };

   list.add(element);

   }
}

return list.ToArray();

Upvotes: 1

Related Questions