118 lines
3.3 KiB
C#
118 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Sarand.Net.Standard.Base.Data
|
|
{
|
|
//=======================================================================
|
|
/// <summary>
|
|
/// Very basic CSV data handling.
|
|
/// <para>For more advanced CSV features, see SaCsvHelper in SacsWinOffice.</para>
|
|
/// </summary>
|
|
public static class SacsCsvHandler
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
|
|
//-------------------------------------------------------------------
|
|
public static String ToCsv (this IEnumerable<String> values, char fieldDelimiter = ',', char textDelimiter = '"')
|
|
{
|
|
String data = "";
|
|
int valueCount = 0;
|
|
foreach (String rawValue in values)
|
|
{
|
|
valueCount++;
|
|
String value = rawValue;
|
|
if (value.Contains(fieldDelimiter.ToString()) || value.Contains(textDelimiter.ToString()))
|
|
value = textDelimiter + value.Replace(textDelimiter.ToString(), textDelimiter.ToString() + textDelimiter.ToString()) + textDelimiter;
|
|
data += (valueCount > 1 ? fieldDelimiter.ToString() : "") + value;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Extract comma delimited fields from data record.
|
|
/// <para>Fields starting with double quotes are terminated with the next single double quotes character.</para>
|
|
/// <para>Embedded double quotes pairs are treated as a single double quotes character.</para>
|
|
/// </summary>
|
|
/// <param name="data"></param>
|
|
/// <returns></returns>
|
|
public static List<String> ParseCsvRecord (String data, char fieldDelimiter = ',', char textDelimiter = '"')
|
|
{
|
|
List<String> fields = new List<string>();
|
|
if (data == null) return fields;
|
|
|
|
// Parse control properties.
|
|
String currentField = "";
|
|
bool inTextField = false;
|
|
bool previousCharTextDelim = false;
|
|
|
|
// Parse the data.
|
|
foreach (char c in data)
|
|
{
|
|
if (inTextField)
|
|
{
|
|
if (c == textDelimiter)
|
|
{
|
|
// Text delimiter found.
|
|
if (!previousCharTextDelim)
|
|
{
|
|
// Make a note that a text delimiter has been found.
|
|
previousCharTextDelim = true;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// 2nd text delimiter found - add single text delimiter to field.
|
|
currentField += c;
|
|
previousCharTextDelim = false;
|
|
continue;
|
|
}
|
|
}
|
|
if (previousCharTextDelim)
|
|
{
|
|
// Non-text delimiter foudn after text delimiter - End of text field.
|
|
inTextField = false;
|
|
previousCharTextDelim = false;
|
|
if (c == fieldDelimiter)
|
|
{
|
|
// End of field.
|
|
fields.Add(currentField);
|
|
currentField = "";
|
|
continue;
|
|
}
|
|
continue;
|
|
}
|
|
currentField += c;
|
|
}
|
|
else
|
|
{
|
|
// Non-text field.
|
|
if (c == fieldDelimiter)
|
|
{
|
|
// End of field.
|
|
fields.Add(currentField);
|
|
currentField = "";
|
|
continue;
|
|
}
|
|
if (currentField.Length == 0 && c == textDelimiter)
|
|
{
|
|
// First character of field is text delimiter.
|
|
inTextField = true;
|
|
continue;
|
|
}
|
|
// Append character to field.
|
|
currentField += c;
|
|
}
|
|
}
|
|
fields.Add(currentField);
|
|
|
|
return fields;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|