mercredi 11 décembre 2024

Parser CSV or FixedWidthFormat

 en C#, write code that can import the content of the input text files to the common data format used by the analysis. The solution should be extensible to handle others formats and display good object oriented principles. Content that does strictly adhere to either of the two formats should be reject with the message The input is not in a valid format. Read input content using Console.ReadLine().Write output to Console.A number of externally sourced text files are required to provide a complete set of data for some business analysis. The content of each file is considered to be the input to the program as a string array with each line being an element of the array. The content maybe in CSV or FixedWidth format. The target format of the output is serialised JSON with all white space removed. The source and target data schemas are mapped as follows: (Target Output Field, Datatype, CSV input field, fixed width input field) have: (OriginalSourceId, String, Ref, characters 1-4), (TransactionDate, DateTime, Date, characters 5-14), (Value, Decimal, Amount, characters 15-22), (Rate, Decimal, Rate, characters 23-27)


using System;

using System.Collections.Generic;

using System.Globalization;

using System.Linq;

using System.Text.Json;

using System.Text.Json.Serialization;


class Program

{

    public static void Main(string[] args)

    {

        Console.WriteLine("Enter the input content line by line, and type 'END' to finish:");


        List<string> inputLines = new();

        string line;

        while ((line = Console.ReadLine()) != "END")

        {

            inputLines.Add(line);

        }


        try

        {

            // Parse the input using a factory method to determine the format

            var parser = ParserFactory.GetParser(inputLines);

            var records = parser.Parse(inputLines);


            // Serialize the list of records with a custom JSON converter

            var jsonOptions = new JsonSerializerOptions

            {

                WriteIndented = false,

                Converters = { new DateTimeConverter() }

            };

            string jsonArray = JsonSerializer.Serialize(records, jsonOptions);


            // Add curly braces around the array to match the exact format

            string jsonOutput = "{[" + jsonArray.TrimStart('[').TrimEnd(']') + "]}";


            Console.WriteLine(jsonOutput);

        }

        catch (Exception ex)

        {

            Console.WriteLine(ex.Message);

        }

    }

}


// Define a custom DateTime converter

public class DateTimeConverter : JsonConverter<DateTime>

{

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)

    {

        return DateTime.ParseExact(reader.GetString(), "yyyy-MM-dd", CultureInfo.InvariantCulture);

    }


    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)

    {

        writer.WriteStringValue(value.ToString("yyyy-MM-dd"));

    }

}


// Define a common record format for output

public class Record

{

    public string OriginalSourceId { get; set; }

    public DateTime TransactionDate { get; set; }

    public decimal Value { get; set; }

    public decimal Rate { get; set; }

}


// Define the base parser interface

public interface IParser

{

    List<Record> Parse(List<string> inputLines);

}


// CSV Parser Implementation

public class CsvParser : IParser

{

    public List<Record> Parse(List<string> inputLines)

    {

        var records = new List<Record>();


        foreach (var line in inputLines)

        {

            var fields = line.Split(',');

            if (fields.Length != 4)

                throw new FormatException("The input is not in a valid format.");


            records.Add(new Record

            {

                OriginalSourceId = fields[0].Trim(),

                TransactionDate = DateTime.ParseExact(fields[1].Trim(), "yyyy-MM-dd", CultureInfo.InvariantCulture),

                Value = decimal.Parse(fields[2].Trim(), CultureInfo.InvariantCulture),

                Rate = decimal.Parse(fields[3].Trim(), CultureInfo.InvariantCulture)

            });

        }


        return records;

    }

}


// Fixed Width Parser Implementation

public class FixedWidthParser : IParser

{

    public List<Record> Parse(List<string> inputLines)

    {

        var records = new List<Record>();


        foreach (var line in inputLines)

        {

            if (line.Length < 27)

                throw new FormatException("The input is not in a valid format.");


            records.Add(new Record

            {

                OriginalSourceId = line.Substring(0, 4).Trim(),

                TransactionDate = DateTime.ParseExact(line.Substring(4, 10).Trim(), "yyyy-MM-dd", CultureInfo.InvariantCulture),

                Value = decimal.Parse(line.Substring(14, 8).Trim(), CultureInfo.InvariantCulture),

                Rate = decimal.Parse(line.Substring(22, 5).Trim(), CultureInfo.InvariantCulture)

            });

        }


        return records;

    }

}


// Factory to determine the correct parser

public static class ParserFactory

{

    public static IParser GetParser(List<string> inputLines)

    {

        if (inputLines == null || !inputLines.Any())

            throw new ArgumentException("The input is not in a valid format.");


        // Check the format of the first line

        var firstLine = inputLines.First();


        if (firstLine.Contains(","))

        {

            return new CsvParser();

        }

        else if (firstLine.Length >= 27)

        {

            return new FixedWidthParser();

        }

        else

        {

            throw new FormatException("The input is not in a valid format.");

        }

    }

}


Aucun commentaire:

Enregistrer un commentaire