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.