A robust, high-performance .NET library for loading, validating, and converting text-based data files into strongly-typed DataTable objects. Seamlessly transform between multiple file formats with built-in validation, column-level type conversion, and comprehensive audit logging.
- Multi-Format Support: Read and write Fixed Length, CSV, Tab-Delimited, Semicolon-Delimited, and Quote-Comma-Delimited files
- Type-Safe Conversion: Automatic conversion to 8 strongly-typed data types with decimal precision control
- Built-in Validation: Column-level validation with allowed value constraints and null-handling
- Comprehensive Audit Logging: Detailed success/error tracking with
AuditLogfor debugging and reporting - Flexible Column Definitions: Define schemas with size constraints, data types, and validation rules
- Zero Dependencies: No external dependencies required
- Cross-Platform: Supports .NET Standard 2.0/2.1, .NET Framework 4.8, and .NET 8
Install-Package Chizl.TextConverter
dotnet add package Chizl.TextConverter
<PackageReference Include="Chizl.TextConverter" />
Note: Omitting the version attribute automatically uses the latest stable release. To pin a specific version, use
Version="x.x.x".
using Chizl.TextConverter;
using System.Data;
// Define column schema
LoadFile loadFile = new(@"C:\data\customers.csv", FileTypes.Comma_Delimited)
{ FirstRowIsHeader = true, TrimValues = true,
ColumnDefinitions = new() {
new ColumnDefinition("CustomerID", DataTypes.Int64),
new ColumnDefinition("Name", DataTypes.String, 50),
new ColumnDefinition("Email", DataTypes.String, 100),
new ColumnDefinition("CreatedDate", DataTypes.DateTime),
new ColumnDefinition("Balance", DataTypes.Decimal, decimalSize: 2),
new ColumnDefinition("IsActive", DataTypes.Boolean)
}
};
// Load and validate
if (loadFile.LoadToDataTable())
{
DataTable customers = loadFile.AsDataTable;
Console.WriteLine($"Loaded {customers.Rows.Count} customers successfully!");
}
else
{
// Handle validation errors
foreach (AuditLog log in loadFile.AuditLogs.Where(l => l.MessageType == MessageTypes.Error))
Console.WriteLine($"[{log.ValidationType}] Line {log.Location}: {log.Message}");
}// Load from CSV
LoadFile loadFile = new(@"C:\data\input.csv", FileTypes.Comma_Delimited)
{
FirstRowIsHeader = true,
ColumnDefinitions = GetColumnDefinitions()
};
if (loadFile.LoadToDataTable())
{
// Save as Fixed Length file
SaveFile saveFile = new(loadFile.AsDataTable, @"C:\data\output.txt",
FileTypes.Fixed_Length_Columns, fileByColDefOnly: true,
overwriteFile: true )
{
FirstRowIsHeader = true,
ColumnDefinitions = loadFile.ColumnDefinitions
};
if (saveFile.Save())
Console.WriteLine("File converted successfully!");
}| File Type | Enum Value | Description |
|---|---|---|
| Fixed Length Columns | FileTypes.Fixed_Length_Columns |
Mainframe-style fixed-width columns |
| CSV (Comma Delimited) | FileTypes.Comma_Delimited |
Standard comma-separated values |
| Quote-Comma Delimited | FileTypes.Quote_Comma_Delimited |
CSV with quoted values ("value","value") |
| Tab Delimited | FileTypes.Tab_Delimited |
Tab-separated values (TSV) |
| Semicolon Delimited | FileTypes.Semicolon_Delimited |
Semicolon-separated values |
| DataType | .NET Type | Notes |
|---|---|---|
DataTypes.String |
System.String |
Use size parameter for max length |
DataTypes.Int64 |
System.Int64 |
Covers all integer types (Int16, Int32, Int64) |
DataTypes.Decimal |
System.Decimal |
Use decimalSize for precision control |
DataTypes.DateTime |
System.DateTime |
Standard date/time parsing |
DataTypes.Boolean |
System.Boolean |
Accepts true/false values |
DataTypes.Guid |
System.Guid |
UUID validation |
DataTypes.TimeSpan |
System.TimeSpan |
Duration/time interval |
DataTypes.ByteArray |
System.Byte[] |
Base64-encoded binary data |
Why Int64 instead of Int32? Since this is a temporary conversion tool,
Int64covers all integer scenarios. Similarly,Decimalcovers floating-point values. SetsizeanddecimalSizefor precision control.
var columnDefinitions = new List<ColumnDefinition>
{
// Required string field with max length
new ColumnDefinition("Status", DataTypes.String, 1)
{
AllowedValues = new List<object> { "A", "I", "P" }
// Active, Inactive, Pending
},
// Nullable integer field
new ColumnDefinition("ManagerID", DataTypes.Int64)
{
AllowDBNull = true
},
// Decimal with 2 decimal places
new ColumnDefinition("Price", DataTypes.Decimal, decimalSize: 2),
// Fixed-width string (for Fixed Length files)
new ColumnDefinition("AccountNumber", DataTypes.String, 10)
};// Example: HUD GSE Loan Limits format
// https://apps.hud.gov/pub/chums/cy2024-gse-limits.txt
LoadFile loadFile = new(@".\data\gse-limits.txt", FileTypes.Fixed_Length_Columns)
{
ColumnDefinitions = new()
{
new ColumnDefinition("MSACode", DataTypes.Int64, 5),
new ColumnDefinition("MetroDivCode", DataTypes.Int64, 5),
new ColumnDefinition("MSAName", DataTypes.String, 50),
new ColumnDefinition("StateCode", DataTypes.String, 5),
new ColumnDefinition("LimitType", DataTypes.String, 1)
{
AllowedValues = new List<object> { "S", "H" } // Standard/High Cost
},
new ColumnDefinition("MedianPrice", DataTypes.Int64, 7),
new ColumnDefinition("LimitFor1Unit", DataTypes.Int64, 7)
}
};
if (loadFile.LoadToDataTable())
Console.WriteLine($"Loaded {loadFile.AsDataTable.Rows.Count} loan limits"); LoadFile loadFile = new(@".\data\file.csv", FileTypes.Comma_Delimited); // ... configure and load ...
// Filter errors only
var errors = loadFile.AuditLogs.Where(log => log.MessageType == MessageTypes.Error).ToList();
foreach (var error in errors)
{
Console.WriteLine($"[{error.ValidationType}] Line {error.Location}");
Console.WriteLine($" Column: {error.Column.Name}");
Console.WriteLine($" Message: {error.Message}");
}
// Export audit log to file
File.WriteAllLines(@".\audit.log", loadFile.AuditLogs.Select(l => $"{l.MessageType} | {l.ValidationType} | Line {l.Location} | {l.Message}"));SaveFile saveFile = new(dataTable, @"C:\data\output.csv", FileTypes.Comma_Delimited)
{
FirstRowIsHeader = true,
TrimValues = true,
ColumnDefinitions = GetColumnDefinitions() // Optional: use same column definitions for formatting
};
if (saveFile.Save())
Console.WriteLine("File saved successfully!");
SaveFile saveFile = new(dataTable: myDataTable,
dstFile: @"C:\output\export.txt",
dstFileType: FileTypes.Quote_Comma_Delimited,
fileByColDefOnly: true, // Use only defined columns (ignore extras)
overwriteFile: true, // Replace existing file
createFolder: true) // Auto-create directory structure
{
FirstRowIsHeader = true,
TrimValues = true,
ColumnDefinitions = columnDefinitions
};
if (!saveFile.Save())
{
// Check for save errors
var saveErrors = saveFile.AuditLogs.Where(l => l.MessageType == MessageTypes.Error);
foreach (var error in saveErrors)
Console.WriteLine($"Error saving file: {error.Message}");
}| Property/Method | Description |
|---|---|
LoadFile(string, FileTypes) |
Constructor: Initialize with file path and type |
ColumnDefinitions |
Define column schema for validation |
FirstRowIsHeader |
Treat first row as column names |
TrimValues |
Auto-trim whitespace from values |
LoadToDataTable() |
Load and validate file into AsDataTable |
AsDataTable |
Access the loaded DataTable |
AuditLogs |
Review validation messages and errors |
| Property/Method | Description |
|---|---|
SaveFile(DataTable, string, FileTypes, ...) |
Constructor: Initialize with source data |
FileByColDefOnly |
Save only columns in ColumnDefinitions |
Save() |
Write file to disk |
AuditLogs |
Review save operation messages |
| Property | Type | Description |
|---|---|---|
Name |
string |
Column name |
DataType |
DataTypes |
Target data type |
Size |
int |
Max length (String) or fixed width |
DecimalSize |
int |
Decimal places (-1 = no rounding) |
AllowedValues |
List<object> |
Whitelist of valid values |
AllowDBNull |
bool |
Allow null/empty values |
Q: Can I load a file without column definitions?
A: No. ColumnDefinitions are required to ensure type safety and validation. This prevents data corruption and provides clear schema documentation.
Q: Why does my nullable column still show DBNull instead of null?
A: DataTable uses DBNull.Value for null database values. Check with dataRow[column] == DBNull.Value or use extension methods to convert.
Q: How do I handle binary data like images?
A: Use DataTypes.ByteArray with Base64 encoding. The library automatically encodes/decodes during save/load operations.
Q: Can I validate values against a specific list?
A: Yes! Set AllowedValues on your ColumnDefinition:
- .NET Standard 2.0+ - Compatible with .NET Core, .NET 5+, .NET Framework 4.6.1+
- .NET Framework 4.8 - Full Framework support
- .NET 8 - Latest .NET platform
- C# 7.3+ - Language features
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes with clear messages
- Push to your branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE.md file for details.
- Homepage: www.chizl.com
- GitHub: github.com/gavin1970/Chizl.TextConverter
- NuGet: nuget.org/packages/Chizl.TextConverter
- Issues: Report a bug or request a feature
- Updated version to because of update into nuget.
- Updated README.md and moved from docs folder to root for Github.
- Visual Studio isn't showing the README.md in NuGet Solution window, but shows it under Package Details.
Still Doesn't show in NuGet Solution window, but at least shows in Package Details.
- Updated version to reflect new dates and reset assembly version to 6.0.0.0.
- Updated README.md
- Original Upload (2024-06-29)
- Stable release
- Multi-target framework support
- Comprehensive audit logging
- Full format conversion capabilities
Made with β€οΈ by Chizl | Β© 2026 chizl.com