/******************************************************************************* * 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 } }