(C# Language) Project Exercise on CSV Processing

A text file contains an unknown number of records. Each record is of the format ABCD,N where ABCD is the code of a supplier and N is a sequence of digits for the amount billed. For example CHD1,34678 is a record with a supplier code of CHD1 and billed amount of 34678. Your program has to read all the records and output a report in a file where all the records are arranged in the increasing order of the amount. The last line shows the sum total. If there is an error in any record the program should exit by printing "Error at record--- ".
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

The Input File

We have to read an input file line by line. This is the file that will be placed on the desktop. The name of the file is "record.txt".


// file called records.txt 
// this file is placed on the desktop 
// directory of the user's computer 

CHD01,23567
PTA02,7879
FZR03,542121
MHL11,3232
JAL22,43432
ASR05,90896

Each record contains two data items separated by a comma. The first part is of exactly 5 characters and contains a supplier code. The second part is a numeric amount.

Video Explanation (see it happen!)

Please watch the following youtube video:

The Desired Output File

We have to process the file and produce an output file called "report.txt". This file contains the same records but sorted in ascending order of the bill amount. The sum total of all the bills appears at the end.


// report.txt 

MHL11,3232
PTA02,7879
CHD01,23567
JAL22,43432
ASR05,90896
FZR03,542121
===============
Total Amount 711127

Create a C# Console Project

First of all create a C# Console Project supporting the latest .NET Core and the C# version 11 or later.


// SupplierBill.cs in Models folder 

internal sealed record class SupplierBill(String? Supplier, int BillAmount);

Create a models folder and add a record class called SupplierBills to hold two properties string? Supplier and int BillAmount.

Program.cs File

Next let us complete the program.cs file.


// program.cs 

string desktopDir = Environment.GetFolderPath(
                      Environment.SpecialFolder.Desktop);

string RECORDSFILE = Path.Combine(desktopDir, "records.txt");
string REPORTFILE = Path.Combine(desktopDir, "report.txt");


List<SupplierBill> allBills = new();

foreach (string line in File.ReadLines(RECORDSFILE))
{
  SupplierBill? bill = null;

  try
  {
    bill = line.Split(",") switch
    {
      // upgrade to version C# 11 
      [var code, var amt] => new (code, Convert.ToInt32(amt)),

      _ => throw new FormatException()
    };
  }
  catch (FormatException)
  {
    Console.WriteLine($"ERROR at {line}");

    return;
  }

  allBills.Add(bill);
}

// using declaration will dispose sw 
// scoping is implicit 
using StreamWriter sw = new (REPORTFILE);

foreach (var bill in allBills.OrderBy(bill => bill.BillAmount))
{
  sw.WriteLine($"{bill.Supplier},{bill.BillAmount}");
}

sw.WriteLine("=========");

sw.WriteLine($"Total {allBills.Sum(bill => bill.BillAmount)}");

Create a list to hold all the records. We shall read the file line by line and extract records into this list.

A for-each loop streams lines from the file one by one. We have used the function File.ReadLines() to stream the lines through IEnumerable.

The line is split into an array on the comma separator, and then pattern matching has been used with switch expression to extract a record or throw a FormatException on failure. Please remember that pattern matching works on C# 11 or later. You will have to upgrade Visual Studio to compile for C# 11 or later.

If the record is extracted, it is added to the list of bills.

A StreamWriter is opened with a using declaration so that the streamwriter is automatically disposed when the object is no longer referenced.

LINQ is used to order the records on BillAmount and a for-each loop is used to printed them to the streamwriter.

Finally, we have again used LINQ to find the sum of all bill amounts and write to the streamwriter.

You can appreciate the brevity of this code!

THE FILE "records.txt" MUST BE PLACED ON DESKTOP BEFORE YOU RUN

Place the "records.txt" file on the desktop and run the project to verify that it works as expected.


This Blog Post/Article "(C# Language) Project Exercise on CSV Processing" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.