/*******************************************************************************
* Copyright(c) 2012 dongke All rights reserved. / Confidential
* 类的信息:
* 1.程序名称:CsvManager.cs
* 2.功能描述:CSV文件与DataTable之间的转换
* 编辑履历:
* 作者 日期 版本 修改内容
* 欧阳涛 2012/07/05 1.00 新建
*******************************************************************************/
using System.Collections;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace Dongke.IBOSS.PRD.Basics.Library
{
///
/// CSV文件与DataTable之间的转换
///
public class CsvManager
{
#region 常量
private const string ROW_END = "\r\n";
#endregion
#region 构造函数
private CsvManager()
{
}
#endregion
#region 公开方法/函数
#region ToDataTable()
public static DataTable ToDataTable(string csv, bool isHeaderFirstRow)
{
return ToDataTable(csv, isHeaderFirstRow, ',', '\"');
}
public static DataTable ToDataTable(string csv, bool isHeaderFirstRow, char delim, char quote)
{
return Decode(csv, isHeaderFirstRow, delim, quote);
}
#endregion
#region ToString()
public static string ToString(DataTable table, bool isHeaderFirstRow)
{
return ToString(table, isHeaderFirstRow, ',', '\"');
}
public static string ToString(DataTable table, bool isHeaderFirstRow, char delim, char quote)
{
return Encode(table, isHeaderFirstRow, delim, quote);
}
public static string ToString(DataColumnCollection columns)
{
return ToString(columns, ',', '\"');
}
public static string ToString(DataColumnCollection columns, char delim, char quote)
{
StringBuilder sb = new StringBuilder();
bool isFirst = true;
foreach (DataColumn column in columns)
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.Append(delim);
}
string item = column.Caption;
if (string.IsNullOrEmpty(item))
{
item = column.ColumnName;
}
sb.Append(QuoteItem(item, delim, quote));
}
sb.Append(ROW_END);
return sb.ToString();
}
public static string ToString(DataRow row)
{
return ToString(row, ',', '\"');
}
public static string ToString(DataRow row, char delim, char quote)
{
if (row == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
bool isFirst = true;
foreach (DataColumn column in row.Table.Columns)
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.Append(delim);
}
sb.Append(QuoteItem(row[column], delim, quote));
}
sb.Append(ROW_END);
return sb.ToString();
}
public static string ToString(System.Windows.Forms.DataGridView dataGridView, bool isHeaderFirstRow)
{
return ToString(dataGridView, isHeaderFirstRow, ',', '\"');
}
public static string ToString(System.Windows.Forms.DataGridView dataGridView, bool isHeaderFirstRow, char delim, char quote)
{
return Encode(dataGridView, isHeaderFirstRow, delim, quote);
}
public static string ToString(DataGridViewRow row)
{
return ToString(row, ',', '\"');
}
public static string ToString(DataGridViewRow row, char delim, char quote)
{
if (row == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
bool isFirst = true;
foreach (DataGridViewColumn column in row.DataGridView.Columns)
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.Append(delim);
}
sb.Append(QuoteItem(row.Cells[column.Index].Value, delim, quote));
}
sb.Append(ROW_END);
return sb.ToString();
}
public static string ToString(DataGridViewColumnCollection columns)
{
return ToString(columns, ',', '\"');
}
public static string ToString(DataGridViewColumnCollection columns, char delim, char quote)
{
StringBuilder sb = new StringBuilder();
bool isFirst = true;
foreach (DataGridViewColumn column in columns)
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.Append(delim);
}
sb.Append(QuoteItem(column.HeaderText, delim, quote));
}
sb.Append(ROW_END);
return sb.ToString();
}
public static string ToString(T[] values, bool isHeaderFirstRow)
{
return ToString(values, isHeaderFirstRow, ',', '\"');
}
public static string ToString(T[] values, bool isHeaderFirstRow, char delim, char quote)
{
if (values == null)
{
return null;
}
StringBuilder sbCsv = new StringBuilder();
bool isFirst = true;
object[] arrays = DataConvert.ToObjectArray(values);
foreach (object value in arrays)
{
if (value == null)
{
return null;
}
if (isFirst)
{
isFirst = false;
}
else
{
sbCsv.Append(delim);
}
sbCsv.Append(QuoteItem(value, delim, quote));
}
return sbCsv.ToString();
}
#endregion
#region QuoteItem()
public static string QuoteItem(object value, char delim, char quote)
{
if (value == null)
{
value = string.Empty;
}
return QuoteItem(value.ToString(), delim, quote);
}
public static string QuoteItem(string item, char delim, char quote)
{
if (string.IsNullOrEmpty(item))
{
return item;
}
if (item.IndexOf(delim) >= 0 || item.IndexOf(quote) >= 0 || item.IndexOf("\r") >= 0 || item.IndexOf("\n") >= 0)
{
return quote + item.Replace(ROW_END, "\n").Replace(quote.ToString(), quote.ToString() + quote.ToString()) + quote;
}
else
{
return item;
}
}
#endregion
#region UnquoteItem()
public static string UnquoteItem(object value, char quote)
{
if (value == null)
{
value = string.Empty;
}
return UnquoteItem(value.ToString(), quote);
}
public static string UnquoteItem(string item, char quote)
{
if (string.IsNullOrEmpty(item))
{
return item;
}
int length = item.Length;
if (item.IndexOf(quote) == 0 && item.LastIndexOf(quote) == length - 1 && 2 <= length)
{
return item.Substring(1, length - 2).Replace(quote.ToString() + quote.ToString(), quote.ToString());
}
else
{
return item;
}
}
#endregion
#endregion
#region 受保护的方法/函数
#region Encode()
protected static string Encode(DataTable table, bool isHeaderFirstRow, char delim, char quote)
{
if (table == null)
{
return null;
}
StringBuilder sbCsv = new StringBuilder();
if (isHeaderFirstRow)
{
sbCsv.Append(ToString(table.Columns, delim, quote));
}
foreach (DataRow row in table.Rows)
{
sbCsv.Append(ToString(row, delim, quote));
}
return sbCsv.ToString();
}
protected static string Encode(System.Windows.Forms.DataGridView dataGridView, bool isHeaderFirstRow, char delim, char quote)
{
if (dataGridView == null)
{
return null;
}
StringBuilder sbCsv = new StringBuilder();
if (isHeaderFirstRow)
{
sbCsv.Append(ToString(dataGridView.Columns, delim, quote));
}
foreach (DataGridViewRow row in dataGridView.Rows)
{
sbCsv.Append(ToString(row, delim, quote));
}
return sbCsv.ToString();
}
#endregion
#region Decode()
protected static DataTable Decode(string csv, bool isHeaderFirstRow, char delim, char quote)
{
DataTable table = new DataTable();
DataRow row;
string[,] result = Decode(csv, delim, quote);
int nRowCount = result.GetLength(0);
int nColumnCount = result.GetLength(1);
for (int j = 0; j < nColumnCount; j++)
{
table.Columns.Add("Column" + j.ToString(), typeof(string));
}
for (int i = 0; i < nRowCount; i++)
{
if (isHeaderFirstRow && i == 0)
{
for (int j = 0; j < nColumnCount; j++)
{
if (string.IsNullOrEmpty(result[i, j]) == false)
{
table.Columns[j].ColumnName = result[i, j];
}
}
}
else
{
row = table.NewRow();
for (int j = 0; j < nColumnCount; j++)
{
if (string.IsNullOrEmpty(result[i, j]) == false)
{
row[j] = result[i, j];
}
}
table.Rows.Add(row);
}
}
return table;
}
protected static string[,] Decode(string csv, char delim, char quote)
{
int nRowCount, nColumnCount;
csv = SanitizeCRLF(csv);
GetCSVCount(csv, out nRowCount, out nColumnCount, delim, quote);
string[,] result = new string[nRowCount, nColumnCount];
int nPtrS = 0;
int nPtrE = 0;
string strLine;
ArrayList aryCSVLine;
int i = 0;
while (nPtrE >= 0)
{
nPtrE = csv.IndexOf(ROW_END, nPtrS);
if (nPtrE < 0)
{
strLine = csv.Substring(nPtrS);
if (strLine == string.Empty)
{
break;
}
}
else
{
strLine = csv.Substring(nPtrS, nPtrE - nPtrS);
}
aryCSVLine = DecodeLine(strLine, delim, quote);
if (aryCSVLine.Count == 0)
{
break;
}
for (int j = 0; j < aryCSVLine.Count; j++)
{
result[i, j] = aryCSVLine[j].ToString();
}
nPtrS = nPtrE + ROW_END.Length;
i++;
}
return result;
}
#endregion
#region GetCSVCount()
protected static void GetCSVCount(string csv, out int rowCount, out int columnCount, char delim, char quote)
{
int nPtrS = 0;
int nPtrE = 0;
string strLine;
ArrayList aryCSVLine;
rowCount = 0;
columnCount = 0;
while (nPtrE >= 0)
{
nPtrE = csv.IndexOf(ROW_END, nPtrS);
if (nPtrE < 0)
{
strLine = csv.Substring(nPtrS);
}
else
{
strLine = csv.Substring(nPtrS, nPtrE - nPtrS);
}
aryCSVLine = DecodeLine(strLine, delim, quote);
if (aryCSVLine.Count == 0)
{
break;
}
if (columnCount < aryCSVLine.Count)
{
columnCount = aryCSVLine.Count;
}
nPtrS = nPtrE + ROW_END.Length;
rowCount++;
}
}
#endregion
#region SanitizeCRLF()
private static string SanitizeCRLF(string csv)
{
if (string.IsNullOrEmpty(csv))
{
return csv;
}
int index = 0;
int maxLength = csv.Length;
StringBuilder result = new StringBuilder();
while (index < maxLength)
{
int preIndex = index;
index = csv.IndexOf('"', index);
if (index < 0)
{
result.Append(csv.Substring(preIndex, maxLength - preIndex));
break;
}
result.Append(csv.Substring(preIndex, index - preIndex));
int startIndex = index;
int endIndex = startIndex;
while (endIndex < maxLength)
{
endIndex = csv.IndexOf('"', endIndex + 1);
if (endIndex < 0)
{
break;
}
if (endIndex + 1 < maxLength && csv.ToCharArray(endIndex + 1, 1)[0] == '"')
{
continue;
}
else
{
break;
}
}
if (endIndex < 0)
{
result.Append(csv.Substring(startIndex, maxLength));
break;
}
else
{
string escapedString = csv.Substring(startIndex, endIndex - startIndex + 1);
escapedString = escapedString.Replace("\r\n", "\n");
result.Append(escapedString);
}
index = endIndex + 1;
}
return result.ToString();
}
#endregion
#region DecodeLine()
protected static ArrayList DecodeLine(string csvLine, char delim, char quote)
{
ArrayList aryCSV = new ArrayList();
int nPtrS = 0;
int nPtrM = 0;
int nPtrE = 0;
string strBuf;
int nCsvLength = csvLine.Length;
if (nCsvLength == 0)
{
return aryCSV;
}
while (nPtrE >= 0)
{
nPtrS = nPtrM = nPtrE;
strBuf = string.Empty;
if (nPtrE >= nCsvLength)
{
break;
}
if (csvLine[nPtrE] == quote)
{
nPtrE++;
while (nPtrE >= 0)
{
nPtrM = nPtrE;
nPtrE = csvLine.IndexOf(quote, nPtrE);
if (nPtrE < 0)
{
strBuf += csvLine.Substring(nPtrM);
break;
}
else
{
strBuf += csvLine.Substring(nPtrM, nPtrE - nPtrM);
}
nPtrM = nPtrE;
if (nPtrE + 1 < nCsvLength && csvLine[nPtrE + 1] == quote)
{
nPtrE += 2;
strBuf += quote;
continue;
}
else
{
nPtrM++;
nPtrE++;
break;
}
}
}
if (nPtrE >= 0)
{
nPtrE = csvLine.IndexOf(delim, nPtrE);
if (nPtrE >= 0)
{
strBuf += csvLine.Substring(nPtrM, nPtrE - nPtrM);
}
else
{
strBuf += csvLine.Substring(nPtrM);
}
aryCSV.Add(strBuf);
}
if (nPtrE < 0)
{
break;
}
nPtrE++;
}
return aryCSV;
}
#endregion
#endregion
}
}