CsvManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /*******************************************************************************
  2. * Copyright(c) 2012 dongke All rights reserved. / Confidential
  3. * 类的信息:
  4. * 1.程序名称:CsvManager.cs
  5. * 2.功能描述:CSV文件与DataTable之间的转换
  6. * 编辑履历:
  7. * 作者 日期 版本 修改内容
  8. * 欧阳涛 2012/07/05 1.00 新建
  9. *******************************************************************************/
  10. using System.Collections;
  11. using System.Data;
  12. using System.Text;
  13. using System.Windows.Forms;
  14. namespace Dongke.IBOSS.PRD.Basics.Library
  15. {
  16. /// <summary>
  17. /// CSV文件与DataTable之间的转换
  18. /// </summary>
  19. public class CsvManager
  20. {
  21. #region 常量
  22. private const string ROW_END = "\r\n";
  23. #endregion
  24. #region 构造函数
  25. private CsvManager()
  26. {
  27. }
  28. #endregion
  29. #region 公开方法/函数
  30. #region ToDataTable()
  31. public static DataTable ToDataTable(string csv, bool isHeaderFirstRow)
  32. {
  33. return ToDataTable(csv, isHeaderFirstRow, ',', '\"');
  34. }
  35. public static DataTable ToDataTable(string csv, bool isHeaderFirstRow, char delim, char quote)
  36. {
  37. return Decode(csv, isHeaderFirstRow, delim, quote);
  38. }
  39. #endregion
  40. #region ToString()
  41. public static string ToString(DataTable table, bool isHeaderFirstRow)
  42. {
  43. return ToString(table, isHeaderFirstRow, ',', '\"');
  44. }
  45. public static string ToString(DataTable table, bool isHeaderFirstRow, char delim, char quote)
  46. {
  47. return Encode(table, isHeaderFirstRow, delim, quote);
  48. }
  49. public static string ToString(DataColumnCollection columns)
  50. {
  51. return ToString(columns, ',', '\"');
  52. }
  53. public static string ToString(DataColumnCollection columns, char delim, char quote)
  54. {
  55. StringBuilder sb = new StringBuilder();
  56. bool isFirst = true;
  57. foreach (DataColumn column in columns)
  58. {
  59. if (isFirst)
  60. {
  61. isFirst = false;
  62. }
  63. else
  64. {
  65. sb.Append(delim);
  66. }
  67. string item = column.Caption;
  68. if (string.IsNullOrEmpty(item))
  69. {
  70. item = column.ColumnName;
  71. }
  72. sb.Append(QuoteItem(item, delim, quote));
  73. }
  74. sb.Append(ROW_END);
  75. return sb.ToString();
  76. }
  77. public static string ToString(DataRow row)
  78. {
  79. return ToString(row, ',', '\"');
  80. }
  81. public static string ToString(DataRow row, char delim, char quote)
  82. {
  83. if (row == null)
  84. {
  85. return null;
  86. }
  87. StringBuilder sb = new StringBuilder();
  88. bool isFirst = true;
  89. foreach (DataColumn column in row.Table.Columns)
  90. {
  91. if (isFirst)
  92. {
  93. isFirst = false;
  94. }
  95. else
  96. {
  97. sb.Append(delim);
  98. }
  99. sb.Append(QuoteItem(row[column], delim, quote));
  100. }
  101. sb.Append(ROW_END);
  102. return sb.ToString();
  103. }
  104. public static string ToString(System.Windows.Forms.DataGridView dataGridView, bool isHeaderFirstRow)
  105. {
  106. return ToString(dataGridView, isHeaderFirstRow, ',', '\"');
  107. }
  108. public static string ToString(System.Windows.Forms.DataGridView dataGridView, bool isHeaderFirstRow, char delim, char quote)
  109. {
  110. return Encode(dataGridView, isHeaderFirstRow, delim, quote);
  111. }
  112. public static string ToString(DataGridViewRow row)
  113. {
  114. return ToString(row, ',', '\"');
  115. }
  116. public static string ToString(DataGridViewRow row, char delim, char quote)
  117. {
  118. if (row == null)
  119. {
  120. return null;
  121. }
  122. StringBuilder sb = new StringBuilder();
  123. bool isFirst = true;
  124. foreach (DataGridViewColumn column in row.DataGridView.Columns)
  125. {
  126. if (isFirst)
  127. {
  128. isFirst = false;
  129. }
  130. else
  131. {
  132. sb.Append(delim);
  133. }
  134. sb.Append(QuoteItem(row.Cells[column.Index].Value, delim, quote));
  135. }
  136. sb.Append(ROW_END);
  137. return sb.ToString();
  138. }
  139. public static string ToString(DataGridViewColumnCollection columns)
  140. {
  141. return ToString(columns, ',', '\"');
  142. }
  143. public static string ToString(DataGridViewColumnCollection columns, char delim, char quote)
  144. {
  145. StringBuilder sb = new StringBuilder();
  146. bool isFirst = true;
  147. foreach (DataGridViewColumn column in columns)
  148. {
  149. if (isFirst)
  150. {
  151. isFirst = false;
  152. }
  153. else
  154. {
  155. sb.Append(delim);
  156. }
  157. sb.Append(QuoteItem(column.HeaderText, delim, quote));
  158. }
  159. sb.Append(ROW_END);
  160. return sb.ToString();
  161. }
  162. public static string ToString<T>(T[] values, bool isHeaderFirstRow)
  163. {
  164. return ToString(values, isHeaderFirstRow, ',', '\"');
  165. }
  166. public static string ToString<T>(T[] values, bool isHeaderFirstRow, char delim, char quote)
  167. {
  168. if (values == null)
  169. {
  170. return null;
  171. }
  172. StringBuilder sbCsv = new StringBuilder();
  173. bool isFirst = true;
  174. object[] arrays = DataConvert.ToObjectArray(values);
  175. foreach (object value in arrays)
  176. {
  177. if (value == null)
  178. {
  179. return null;
  180. }
  181. if (isFirst)
  182. {
  183. isFirst = false;
  184. }
  185. else
  186. {
  187. sbCsv.Append(delim);
  188. }
  189. sbCsv.Append(QuoteItem(value, delim, quote));
  190. }
  191. return sbCsv.ToString();
  192. }
  193. #endregion
  194. #region QuoteItem()
  195. public static string QuoteItem(object value, char delim, char quote)
  196. {
  197. if (value == null)
  198. {
  199. value = string.Empty;
  200. }
  201. return QuoteItem(value.ToString(), delim, quote);
  202. }
  203. public static string QuoteItem(string item, char delim, char quote)
  204. {
  205. if (string.IsNullOrEmpty(item))
  206. {
  207. return item;
  208. }
  209. if (item.IndexOf(delim) >= 0 || item.IndexOf(quote) >= 0 || item.IndexOf("\r") >= 0 || item.IndexOf("\n") >= 0)
  210. {
  211. return quote + item.Replace(ROW_END, "\n").Replace(quote.ToString(), quote.ToString() + quote.ToString()) + quote;
  212. }
  213. else
  214. {
  215. return item;
  216. }
  217. }
  218. #endregion
  219. #region UnquoteItem()
  220. public static string UnquoteItem(object value, char quote)
  221. {
  222. if (value == null)
  223. {
  224. value = string.Empty;
  225. }
  226. return UnquoteItem(value.ToString(), quote);
  227. }
  228. public static string UnquoteItem(string item, char quote)
  229. {
  230. if (string.IsNullOrEmpty(item))
  231. {
  232. return item;
  233. }
  234. int length = item.Length;
  235. if (item.IndexOf(quote) == 0 && item.LastIndexOf(quote) == length - 1 && 2 <= length)
  236. {
  237. return item.Substring(1, length - 2).Replace(quote.ToString() + quote.ToString(), quote.ToString());
  238. }
  239. else
  240. {
  241. return item;
  242. }
  243. }
  244. #endregion
  245. #endregion
  246. #region 受保护的方法/函数
  247. #region Encode()
  248. protected static string Encode(DataTable table, bool isHeaderFirstRow, char delim, char quote)
  249. {
  250. if (table == null)
  251. {
  252. return null;
  253. }
  254. StringBuilder sbCsv = new StringBuilder();
  255. if (isHeaderFirstRow)
  256. {
  257. sbCsv.Append(ToString(table.Columns, delim, quote));
  258. }
  259. foreach (DataRow row in table.Rows)
  260. {
  261. sbCsv.Append(ToString(row, delim, quote));
  262. }
  263. return sbCsv.ToString();
  264. }
  265. protected static string Encode(System.Windows.Forms.DataGridView dataGridView, bool isHeaderFirstRow, char delim, char quote)
  266. {
  267. if (dataGridView == null)
  268. {
  269. return null;
  270. }
  271. StringBuilder sbCsv = new StringBuilder();
  272. if (isHeaderFirstRow)
  273. {
  274. sbCsv.Append(ToString(dataGridView.Columns, delim, quote));
  275. }
  276. foreach (DataGridViewRow row in dataGridView.Rows)
  277. {
  278. sbCsv.Append(ToString(row, delim, quote));
  279. }
  280. return sbCsv.ToString();
  281. }
  282. #endregion
  283. #region Decode()
  284. protected static DataTable Decode(string csv, bool isHeaderFirstRow, char delim, char quote)
  285. {
  286. DataTable table = new DataTable();
  287. DataRow row;
  288. string[,] result = Decode(csv, delim, quote);
  289. int nRowCount = result.GetLength(0);
  290. int nColumnCount = result.GetLength(1);
  291. for (int j = 0; j < nColumnCount; j++)
  292. {
  293. table.Columns.Add("Column" + j.ToString(), typeof(string));
  294. }
  295. for (int i = 0; i < nRowCount; i++)
  296. {
  297. if (isHeaderFirstRow && i == 0)
  298. {
  299. for (int j = 0; j < nColumnCount; j++)
  300. {
  301. if (string.IsNullOrEmpty(result[i, j]) == false)
  302. {
  303. table.Columns[j].ColumnName = result[i, j];
  304. }
  305. }
  306. }
  307. else
  308. {
  309. row = table.NewRow();
  310. for (int j = 0; j < nColumnCount; j++)
  311. {
  312. if (string.IsNullOrEmpty(result[i, j]) == false)
  313. {
  314. row[j] = result[i, j];
  315. }
  316. }
  317. table.Rows.Add(row);
  318. }
  319. }
  320. return table;
  321. }
  322. protected static string[,] Decode(string csv, char delim, char quote)
  323. {
  324. int nRowCount, nColumnCount;
  325. csv = SanitizeCRLF(csv);
  326. GetCSVCount(csv, out nRowCount, out nColumnCount, delim, quote);
  327. string[,] result = new string[nRowCount, nColumnCount];
  328. int nPtrS = 0;
  329. int nPtrE = 0;
  330. string strLine;
  331. ArrayList aryCSVLine;
  332. int i = 0;
  333. while (nPtrE >= 0)
  334. {
  335. nPtrE = csv.IndexOf(ROW_END, nPtrS);
  336. if (nPtrE < 0)
  337. {
  338. strLine = csv.Substring(nPtrS);
  339. if (strLine == string.Empty)
  340. {
  341. break;
  342. }
  343. }
  344. else
  345. {
  346. strLine = csv.Substring(nPtrS, nPtrE - nPtrS);
  347. }
  348. aryCSVLine = DecodeLine(strLine, delim, quote);
  349. if (aryCSVLine.Count == 0)
  350. {
  351. break;
  352. }
  353. for (int j = 0; j < aryCSVLine.Count; j++)
  354. {
  355. result[i, j] = aryCSVLine[j].ToString();
  356. }
  357. nPtrS = nPtrE + ROW_END.Length;
  358. i++;
  359. }
  360. return result;
  361. }
  362. #endregion
  363. #region GetCSVCount()
  364. protected static void GetCSVCount(string csv, out int rowCount, out int columnCount, char delim, char quote)
  365. {
  366. int nPtrS = 0;
  367. int nPtrE = 0;
  368. string strLine;
  369. ArrayList aryCSVLine;
  370. rowCount = 0;
  371. columnCount = 0;
  372. while (nPtrE >= 0)
  373. {
  374. nPtrE = csv.IndexOf(ROW_END, nPtrS);
  375. if (nPtrE < 0)
  376. {
  377. strLine = csv.Substring(nPtrS);
  378. }
  379. else
  380. {
  381. strLine = csv.Substring(nPtrS, nPtrE - nPtrS);
  382. }
  383. aryCSVLine = DecodeLine(strLine, delim, quote);
  384. if (aryCSVLine.Count == 0)
  385. {
  386. break;
  387. }
  388. if (columnCount < aryCSVLine.Count)
  389. {
  390. columnCount = aryCSVLine.Count;
  391. }
  392. nPtrS = nPtrE + ROW_END.Length;
  393. rowCount++;
  394. }
  395. }
  396. #endregion
  397. #region SanitizeCRLF()
  398. private static string SanitizeCRLF(string csv)
  399. {
  400. if (string.IsNullOrEmpty(csv))
  401. {
  402. return csv;
  403. }
  404. int index = 0;
  405. int maxLength = csv.Length;
  406. StringBuilder result = new StringBuilder();
  407. while (index < maxLength)
  408. {
  409. int preIndex = index;
  410. index = csv.IndexOf('"', index);
  411. if (index < 0)
  412. {
  413. result.Append(csv.Substring(preIndex, maxLength - preIndex));
  414. break;
  415. }
  416. result.Append(csv.Substring(preIndex, index - preIndex));
  417. int startIndex = index;
  418. int endIndex = startIndex;
  419. while (endIndex < maxLength)
  420. {
  421. endIndex = csv.IndexOf('"', endIndex + 1);
  422. if (endIndex < 0)
  423. {
  424. break;
  425. }
  426. if (endIndex + 1 < maxLength && csv.ToCharArray(endIndex + 1, 1)[0] == '"')
  427. {
  428. continue;
  429. }
  430. else
  431. {
  432. break;
  433. }
  434. }
  435. if (endIndex < 0)
  436. {
  437. result.Append(csv.Substring(startIndex, maxLength));
  438. break;
  439. }
  440. else
  441. {
  442. string escapedString = csv.Substring(startIndex, endIndex - startIndex + 1);
  443. escapedString = escapedString.Replace("\r\n", "\n");
  444. result.Append(escapedString);
  445. }
  446. index = endIndex + 1;
  447. }
  448. return result.ToString();
  449. }
  450. #endregion
  451. #region DecodeLine()
  452. protected static ArrayList DecodeLine(string csvLine, char delim, char quote)
  453. {
  454. ArrayList aryCSV = new ArrayList();
  455. int nPtrS = 0;
  456. int nPtrM = 0;
  457. int nPtrE = 0;
  458. string strBuf;
  459. int nCsvLength = csvLine.Length;
  460. if (nCsvLength == 0)
  461. {
  462. return aryCSV;
  463. }
  464. while (nPtrE >= 0)
  465. {
  466. nPtrS = nPtrM = nPtrE;
  467. strBuf = string.Empty;
  468. if (nPtrE >= nCsvLength)
  469. {
  470. break;
  471. }
  472. if (csvLine[nPtrE] == quote)
  473. {
  474. nPtrE++;
  475. while (nPtrE >= 0)
  476. {
  477. nPtrM = nPtrE;
  478. nPtrE = csvLine.IndexOf(quote, nPtrE);
  479. if (nPtrE < 0)
  480. {
  481. strBuf += csvLine.Substring(nPtrM);
  482. break;
  483. }
  484. else
  485. {
  486. strBuf += csvLine.Substring(nPtrM, nPtrE - nPtrM);
  487. }
  488. nPtrM = nPtrE;
  489. if (nPtrE + 1 < nCsvLength && csvLine[nPtrE + 1] == quote)
  490. {
  491. nPtrE += 2;
  492. strBuf += quote;
  493. continue;
  494. }
  495. else
  496. {
  497. nPtrM++;
  498. nPtrE++;
  499. break;
  500. }
  501. }
  502. }
  503. if (nPtrE >= 0)
  504. {
  505. nPtrE = csvLine.IndexOf(delim, nPtrE);
  506. if (nPtrE >= 0)
  507. {
  508. strBuf += csvLine.Substring(nPtrM, nPtrE - nPtrM);
  509. }
  510. else
  511. {
  512. strBuf += csvLine.Substring(nPtrM);
  513. }
  514. aryCSV.Add(strBuf);
  515. }
  516. if (nPtrE < 0)
  517. {
  518. break;
  519. }
  520. nPtrE++;
  521. }
  522. return aryCSV;
  523. }
  524. #endregion
  525. #endregion
  526. }
  527. }