CSV Reader - How To Quickly Change Field Delimiter In CSV Document

Introduction

While working on development of simple application in C#, for creating and printing some plain specification of goods and services with its prices, a problem with the local regional number notation was evolved. Use of comma for decimal symbol in numbers. So there was a need to change field delimiter comma inside initial RFC 4180 standard CSV document to different character like semicolon, so that in further use of this document, C# method for reading data becomes far more efficient and fast.

There is a simple solution for this problem, just open CSV file in MS Excel and save data back with changed field delimiter in save options. :))))))

Here is a method that reads RFC 4180 standard CSV document, extracts field values from records, changes field delimiter from comma to any selected, and saves newly created record back to new file,

/// <summary>
/// Read RFC 4180 standard CSV document ,
/// extract field values from records ,
/// change field delimiter from comma to any selected,
/// and save newly created record back to new CSV file.
/// </summary>
/// <param name="Source_CSV">RFC 4180 standard CSV document file path.</param>
/// <param name="Target">New document file path.</param>
/// <param name="NEW_FIELD_DELIMITER">Character that will replace comma,
/// RFC 4180 standard CSV document field delimiter.</param>
private static void Change_Field_Delimiter(string Source_CSV, string Target, char NEW_FIELD_DELIMITER) {
    // Source CSV document path and encoding
    StreamReader sr = new StreamReader(Source_CSV, Encoding.UTF8);
    // Target CSV document path and encoding
    StreamWriter sw = new StreamWriter(Target, false, Encoding.UTF8);
    // RFC 4180 standard delimiters
    const int Field_delimiter = ',';
    const int String_delimiter = '"';
    const int Carriage_Return = '\r';
    const int Line_Feed = '\n';
    // Record
    StringBuilder Record = new StringBuilder();
    // Single character ASCII code value
    // in Source_CSV document line
    // Value of -1 means End Of File
    int Character = -1;
    // If exists read first character from Source_CSV document
    Character = sr.Read();
    // While not End Of File
    while (Character != -1) {
        // If first character
        // in Field value is string delimiter
        if (Character == String_delimiter) {
            // Skip string delimiter
            while (Character != -1) {
                Character = sr.Read();
                if (Character == String_delimiter) {
                    // Skip string delimiter
                    Character = sr.Read();
                    if (Character == String_delimiter) {
                        // Get string delimiter to record field
                        Record.Append((char) Character);
                    } else if (Character == Field_delimiter) {
                        // Change old to new field delimiter
                        Record.Append(NEW_FIELD_DELIMITER);
                        Character = sr.Read();
                        break;
                    } else {
                        // Possible CR or LF or -1
                        // or error in CSV document
                        break;
                    }
                } else {
                    // Get character to record field
                    Record.Append((char) Character);
                }
            }
        }
        if (Character != String_delimiter) {
            while (Character != Field_delimiter && Character != Carriage_Return && Character != Line_Feed && Character != -1) {
                // Get character
                Record.Append((char) Character);
                Character = sr.Read();
            }
            if (Character == Field_delimiter) {
                // Change old to new field delimiter
                Record.Append(NEW_FIELD_DELIMITER);
            }
            Character = sr.Read();
            if (Character == Line_Feed) {
                // Write new Record with
                // all Fields separated with new delimiter
                // in new line to target document
                sw.WriteLine(Record);
                Record.Clear();
                Character = sr.Read();
            }
        }
    }
    // Write last Record with
    // all Fields separated with new delimiter
    // in new line to target document
    sw.Write(Record);
    Record.Clear();
    // Close and dispose Source stream reader
    sr.Close();
    sr.Dispose();
    // Close and dispose Target stream writer
    sw.Close();
    sw.Dispose();
}

NOTICE

This method expects that Source CSV  file is absolutely correct and created strictly according to RFC 4180 standard for CSV documents.