user3612950
user3612950

Reputation: 41

C# Read text file and print out in to a table

I'm trying to read a text file and print out into a table. I want the output to be this

enter image description here

But now I having different output

enter image description here

var column1 = new List<string>();
var column2 = new List<string>();
var column3 = new List<string>();

using (var rd = new StreamReader(@"C:\test.txt"))
{
    while (!rd.EndOfStream)
    {
          var splits = rd.ReadLine().Split(';');
          column1.Add(splits[0]);
          column2.Add(splits[1]);
          column3.Add(splits[2]);
    }
}

Console.WriteLine("Date/Time \t Movie \t Seat");
foreach (var element in column1) Console.WriteLine(element); 
foreach (var element in column2) Console.WriteLine(element);
foreach (var element in column3) Console.WriteLine(element);

Upvotes: 1

Views: 2336

Answers (3)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186678

You can use Linq to construct a convenient structure (e.g. List<String[]>) and then print out all the data wanted:

List<String[]> data = File
  .ReadLines(@"C:\test.txt")
 //.Skip(1) // <- uncomment this to skip caption if the csv has it
  .Select(line => line.Split(';').Take(3).ToArray()) // 3 items only
  .ToList();

// Table output (wanted one):
String report = String.Join(Environment.NewLine, 
  data.Select(items => String.Join("\t", items)));   

Console.WriteLine(report);

// Column after column output (actual one)
Console.WriteLine(String.Join(Environment.NewLine, data.Select(item => item[0])));
Console.WriteLine(String.Join(Environment.NewLine, data.Select(item => item[1])));
Console.WriteLine(String.Join(Environment.NewLine, data.Select(item => item[2])));

EDIT: if you want to choose the movie, buy the ticket etc. elaborate the structure:

  // Create a custom class where implement your logic 
  public class MovieRecord {
    private Date m_Start;
    private String m_Name;
    private int m_Seats;

    ... 
    public MovieRecord(DateTime start, String name, int seats) {
      ...
      m_Seats = seats;
      ...
    }
    ...

    public String ToString() {
      return String.Join("\t", m_Start, m_Name, m_Seats);
    }

    public void Buy() {...}
    ...
  }

And then convert to conventinal structure:

  List<MovieRecord> data = File
    .ReadLines(@"C:\test.txt")
    //.Skip(1) // <- uncomment this to skip caption if the csv has it
    .Select(line => {
       String items[] = line.Split(';'); 
       return new MovieRecord(
         DateTime.ParseExact(items[0], "PutActualFormat", CultureInfo.InvariantCulture), 
         items[1], 
         int.Parse(items[2]));
    }
    .ToList();

And the table output will be

  Console.Write(String.Join(Envrironment.NewLine, data));

Upvotes: 1

TVOHM
TVOHM

Reputation: 2742

You could attempt to solve this in a more Object-Orientated manner, which might make it a bit easier for you to work with:

You can declare a simple class to represent a movie seat:

class MovieSeat
{
    public readonly string Date, Name, Number;

    public MovieSeat(string source)
    {
        string[] data = source.Split(';');
        Date = data[0];
        Name = data[1];
        Number = data[2];
    }
}

And then you can read in and print out the data in a few lines of code:

// Read in the text file and create a new MovieSeat object for each line in the file.
// Iterate over all MovieSeat objets and print them to console.
foreach(var seat in File.ReadAllLines(@"C:\test.txt").Select(x => new MovieSeat(x)))
    Console.WriteLine(string.Join("\t", seat.Date, seat.Name, seat.Number));

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460108

Don't use Console.WriteLine if you want to add a "column". You should also use a single List<string[]> instead of multiple List<string>.

List<string[]> allLineFields = new List<string[]>();
using (var rd = new StreamReader(@"C:\test.txt"))
{
    while (!rd.EndOfStream)
    {
        var splits = rd.ReadLine().Split(';');
        allLineFields.Add(splits);
    }
}

Console.WriteLine("Date/Time \t Movie \t Seat");
foreach(string[] line in allLineFields)
    Console.WriteLine(String.Join("\t", line)); 

In general you should use a real csv parser if you want to parse a csv-file, not string methods or regex.

You could use the TextFieldParser which is the only one available in the framework directly:

var allLineFields = new List<string[]>();
using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(@"C:\test.txt"))
{
    parser.Delimiters = new string[] { ";" };
    parser.HasFieldsEnclosedInQuotes = false; // very useful 
    string[] lineFields;
    while ((lineFields = parser.ReadFields()) != null)
    {
        allLineFields.Add(lineFields);
    }
}

You need to add a reference to the Microsoft.VisualBasic dll to your project.

There are other available: Parsing CSV files in C#, with header

Upvotes: 0

Related Questions