FixedWidth.FileParser 3.0.0

dotnet add package FixedWidth.FileParser --version 3.0.0                
NuGet\Install-Package FixedWidth.FileParser -Version 3.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FixedWidth.FileParser" Version="3.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FixedWidth.FileParser --version 3.0.0                
#r "nuget: FixedWidth.FileParser, 3.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install FixedWidth.FileParser as a Cake Addin
#addin nuget:?package=FixedWidth.FileParser&version=3.0.0

// Install FixedWidth.FileParser as a Cake Tool
#tool nuget:?package=FixedWidth.FileParser&version=3.0.0                

FileUtil v3.0.0

NuGet version License: MIT CI GitHub Release CodeQL .Net

.Net Library to read from fixed width or delimiter separated file using strongly typed objects.

Fixed Width or Delimiter Separated File

What is Fixed width or Delimiter separated text files?

Fixed width or Delimiter separeted text file is a file that has a specific format which allows for the manipulation of textual information in an organized fashion.
Each row contains one record of information; each record can contain multiple pieces of data fields or columns. The data columns are separated by any character you specify called the delimiter. All rows in the file follow a consistent format and should be with the same number of data columns. Data columns could be empty with no value.

**CASE 1 😗* Simple pipe '|' separated Delimeter File is shown below (this could even be comma ',' separated CSV)

|Mr|Jack Marias|Male|London|Active|||
|Dr|Bony Stringer|Male|New Jersey|Active||Paid|
|Mrs|Mary Ward|Female||Active|||
|Mr|Robert Webb|||Active|||

CASE 2: The above file could have a header and a footer. In which case, each row has an identifier called as Line head to determine the type of row in the file.

|H|Department|Jun 23 2016  7:01PM|
|D||Jack Marias|Male|London|Active|||
|D|Dr|Bony Stringer|Male|New Jersey|Active||Paid|
|D|Mrs|Mary Ward|Female||Active|||
|D|Mr|Robert Webb|||Active|||
|F|4 Records|

FileUtil can be used to parse both of the shown formats above. The line heads and data column delimiters (separators) are configurable as required per use case.


Using FileUtil

Note: This file will have rows with no line head as all lines are of same type ie. default is type of data.

For the example rows below, we can parse the file with just few lines of code and minimal configuration.

|Mr|Jack Marias|Male|London|
|Dr|Bony Stringer|Male|New Jersey|
|Mrs|Mary Ward|Female||
|Mr|Robert Webb|||

Configuration

We can configure the parser and provider setting for FileUtil to override the defaults.

The below configuration shows the complete set of attributes required to parse a delimiter separated file with no header or footer rows.

At a minimal you can specify the folder location {"providerSettings":{ "folderPath":"C:work"} where the source file will reside. You can override defaults as required.

By default, the file is read using the default file system provider. You can pass in your own implementation of the provider > to custom read file from desired location. We will later show how you can acheive this.

{
    "configSettings":{
        "parserSettings": { "delimiter":{ "value":"|"} },
        "providerSettings": {
                "folderPath":"C:work",
                "fileNameFormat":"File*.txt",
                "archiveUponRead":"true",
                "archiveFolder":"Archived"
    }
}	

}

The "fileNameFormat":"File*.txt" attribute (by default is empty) can be used to search the folder location for files with a specific name pattern. if not specified then all available files in the folder location will be searched.

Code

To parse a row into a C# class, you need to implement FileLine abstract class. By doing this you create a strongly typed line representation for each row in the file.

Consider the file below -

|Mr|Jack Marias|Male|London|
|Dr|Bony Stringer|Male|New Jersey|
|Mrs|Mary Ward|Female||
|Mr|Robert Webb|||

Let us create an employee class which will hold data for each row shown in the file above. The properties in the line class should match to the column index and data type of the fields of the row.

We use the column attribute to specify the column index and can optionally specify a default value for the associated column should it be be empty. As a rule of thumb, the number of properties with column attributes should match the number of columns in the row else the engine will throw an exception.

FileLine base class has an index property that holds the index of the parsed line relative to the whole file, an array of errors (should there be any column parsing failures) and type property to denote if the file is of type header, data or footer (default is data)

 public class Employee : FileLine
    {
        [Column(0)]
        public string Title { get; set; }
        [Column(1)]
        public string Name { get; set; }
        [Column(2)]
        public string Sex { get; set; }
        [Column(3, "London")]
        public string Location { get; set; }
    } 

Once you have created the line class it is as simple as calling the Engine.GetFile() method as follows

var files = new Engine(configSettings).GetFiles<Employee>();

The engine will parse the files found at the specified folder location and return a collection of File<Employee> objects ie. one for each file parsed with an array of strongly typed lines (in this case Employee[]).

public class File<T> where T: FileLine
    {
        /// <summary>
        /// File meta data.
        /// </summary>
        public FileMeta FileMeta { get; set; }
        /// <summary>
        /// Strongly typed parsed lines.
        /// </summary>
        public T[] Data { get; set; }
       
    }

Note: This file will have rows with line head to determine each row type. By default, the line heads are 'H' for header, 'D' for data and 'F' for footer respectively. all these line heads are configurable via the config.

|H|Department|Jun 23 2016  7:01PM|
|D|Mr|Jack Marias|Male|London|
|D|Dr|Bony Stringer|Male|New Jersey|
|D|Mrs|Mary Ward|Female||
|D|Mr|Robert Webb|||
|F|4 Records|

Configuration

The configuration is the same as before. We can override the default line heads by specifying the required line head attribute in the parser settings.

{
    "configSettings":{
        "parserSettings":{ "delimiter": { "value":"|"} ,
                           "lineHeaders": { 
                                "header":"H", 
                                "footer":"F", 
                                "data":"D" 
                            }
        },
        "providerSettings":{
                        "folderPath":"C:work",
                        "fileNameFormat":"File*.txt",
                        "archiveUponRead":"true",
                        "archiveFolder":"Archived"
        }		
    }	  
}

Code

Like before we need a line class to map to each type of the row in the file ie one for the header, footer and data line respectively.

We continue by creating two extra classes HeaderLine and FooterLine as follows.

 public class Header : FileLine
    {
        [Column(0)]
        public string Name { get; set; }
        [Column(1)]
        public DateTime Date { get; set; }
    } 

 public class Footer : FileLine
    {
        [Column(0)]
        public string FileRemarks { get; set; }
    } 

To parse the file you call the GetFiles() Method as follows -

var files = new Engine(configSettings).GetFiles<Header, Employee, Footer>();

The engine will parse the files and return a collection of File<Header, Employee, Footer> objects ie. one for each file parsed with strongly typed header, footer and data line arrays.


Custom File Provider: Let us see how we can implement custom file provider for bespoke requirements.

You can implement your own custom provider and pass it to the engine to provide delimiter separated file lines by implementing your own bespoke logic. This could be reading the contents from the datadase or over http, etc.

To implement a custom provider you need to implement IFileProvide interface

An example dummy implementation is as follows

 public class CustomProvider : IFileProvider
{
    public FileMeta[] GetFiles()
    {
       // custom implementation to return file lines 
        return new[]
        {
            new FileMeta
            {
                FileName = "Name",
                FileSize = 100,
                FilePath = "File Path",
                Lines = new[] {"H|22-10-2016|Employee Status", "D|John Walsh|456RT4|True", "F|1"}
            }
        };
    }
}

You can pass the custom provider to the engine as follows -

var files = new Engine(configSettings, new CustomProvider()).GetFiles<Employee>();

var files = new Engine(configSettings, new CustomProvider()).GetFiles<Header, Employee, Footer>();

Returns

public class File<TH, TD, TF> 
    {
        /// <summary>
        /// File meta data.
        /// </summary>
        public FileMeta FileMeta { get; set; }
        /// <summary>
        /// Parsed header lines.
        /// </summary>
        public TH Header { get; set; }
        /// <summary>
        /// Parsed data lines.
        /// </summary>
        public TD[] Data { get; set; }
        /// <summary>
        /// Parsed footer line.
        /// </summary>
        public TF Footer { get; set; }
    }

Credits

Thank you for reading. Please fork, explore, contribute and report. Happy Coding !! 😃

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0 331 4/6/2024
2.0.0 209 6/27/2023
1.1.1 138 5/18/2023
1.1.0 995 9/5/2019
1.0.4 724 11/12/2018