| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Data;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace ToolsClassLibrary
- {
- /// <summary>
- /// CSV工具类
- /// </summary>
- public class CsvStreamReader
- {
- /// <summary>
- /// 行链表,CSV文件的每一行就是一个链
- /// </summary>
- private ArrayList rowAL; //行链表,CSV文件的每一行就是一个链
- /// <summary>
- /// 文件名
- /// </summary>
- private string fileName; //文件名
- /// <summary>
- /// 编码
- /// </summary>
- private Encoding encoding; //编码
- public CsvStreamReader()
- {
- this.rowAL = new ArrayList();
- this.fileName = "";
- this.encoding = Encoding.Default;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="fileName">文件名,包括文件路径</param>
- public CsvStreamReader(string fileName)
- {
- this.rowAL = new ArrayList();
- this.fileName = fileName;
- this.encoding = Encoding.Default;
- LoadCsvFile();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="fileName">文件名,包括文件路径</param>
- /// <param name="encoding">文件编码</param>
- public CsvStreamReader(string fileName, Encoding encoding)
- {
- this.rowAL = new ArrayList();
- this.fileName = fileName;
- this.encoding = encoding;
- LoadCsvFile();
- }
- /// <summary>
- /// 文件名,包括文件路径
- /// </summary>
- public string FileName
- {
- set
- {
- this.fileName = value;
- LoadCsvFile();
- }
- }
- /// <summary>
- /// 文件编码
- /// </summary>
- public Encoding FileEncoding
- {
- set
- {
- this.encoding = value;
- }
- }
- /// <summary>
- /// 获取行数
- /// </summary>
- public int RowCount
- {
- get
- {
- return this.rowAL.Count;
- }
- }
- /// <summary>
- /// 获取列数
- /// </summary>
- public int ColCount
- {
- get
- {
- int maxCol;
- maxCol = 0;
- for (int i = 0; i < this.rowAL.Count; i++)
- {
- ArrayList colAL = (ArrayList)this.rowAL[i];
- maxCol = (maxCol > colAL.Count) ? maxCol : colAL.Count;
- }
- return maxCol;
- }
- }
- /// <summary>
- /// 获取某行某列的数据
- /// row:行,row = 1代表第一行
- /// col:列,col = 1代表第一列
- /// </summary>
- public string this[int row, int col]
- {
- get
- {
- //数据有效性验证
- CheckRowValid(row);
- CheckColValid(col);
- ArrayList colAL = (ArrayList)this.rowAL[row - 1];
- //如果请求列数据大于当前行的列时,返回空值
- if (colAL.Count < col)
- {
- return "";
- }
- return colAL[col - 1].ToString();
- }
- }
- /// <summary>
- /// 根据最小行,最大行,最小列,最大列,来生成一个DataTable类型的数据
- /// 行等于1代表第一行
- /// 列等于1代表第一列
- /// maxrow: -1代表最大行
- /// maxcol: -1代表最大列
- /// </summary>
- public DataTable this[int minRow, int maxRow, int minCol, int maxCol]
- {
- get
- {
- //数据有效性验证
- CheckRowValid(minRow);
- CheckMaxRowValid(maxRow);
- CheckColValid(minCol);
- CheckMaxColValid(maxCol);
- if (maxRow == -1)
- {
- maxRow = RowCount;
- }
- if (maxCol == -1)
- {
- maxCol = ColCount;
- }
- if (maxRow < minRow)
- {
- throw new Exception("最大行数不能小于最小行数");
- }
- if (maxCol < minCol)
- {
- throw new Exception("最大列数不能小于最小列数");
- }
- DataTable csvDT = new DataTable();
- int i;
- int col;
- int row;
- //增加列
- for (i = minCol; i <= maxCol; i++)
- {
- csvDT.Columns.Add(i.ToString());
- }
- for (row = minRow; row <= maxRow; row++)
- {
- DataRow csvDR = csvDT.NewRow();
- i = 0;
- for (col = minCol; col <= maxCol; col++)
- {
- csvDR[i] = this[row, col];
- i++;
- }
- csvDT.Rows.Add(csvDR);
- }
- return csvDT;
- }
- }
- /// <summary>
- /// 检查行数是否是有效的
- /// </summary>
- /// <param name="col"></param>
- private void CheckRowValid(int row)
- {
- if (row <= 0)
- {
- throw new Exception("行数不能小于0");
- }
- if (row > RowCount)
- {
- throw new Exception("没有当前行的数据");
- }
- }
- /// <summary>
- /// 检查最大行数是否是有效的
- /// </summary>
- /// <param name="col"></param>
- private void CheckMaxRowValid(int maxRow)
- {
- if (maxRow <= 0 && maxRow != -1)
- {
- throw new Exception("行数不能等于0或小于-1");
- }
- if (maxRow > RowCount)
- {
- throw new Exception("没有当前行的数据");
- }
- }
- /// <summary>
- /// 检查列数是否是有效的
- /// </summary>
- /// <param name="col"></param>
- private void CheckColValid(int col)
- {
- if (col <= 0)
- {
- throw new Exception("列数不能小于0");
- }
- if (col > ColCount)
- {
- throw new Exception("没有当前列的数据");
- }
- }
- /// <summary>
- /// 检查检查最大列数是否是有效的
- /// </summary>
- /// <param name="col"></param>
- private void CheckMaxColValid(int maxCol)
- {
- if (maxCol <= 0 && maxCol != -1)
- {
- throw new Exception("列数不能等于0或小于-1");
- }
- if (maxCol > ColCount)
- {
- throw new Exception("没有当前列的数据");
- }
- }
- /// <summary>
- /// 载入CSV文件
- /// </summary>
- private void LoadCsvFile()
- {
- //对数据的有效性进行验证
- if (this.fileName == null)
- {
- throw new Exception("请指定要载入的CSV文件名");
- }
- else if (!File.Exists(this.fileName))
- {
- throw new Exception("指定的CSV文件不存在");
- }
- else
- {
- }
- if (this.encoding == null)
- {
- this.encoding = Encoding.Default;
- }
- StreamReader sr = new StreamReader(this.fileName, this.encoding);
- string csvDataLine;
- csvDataLine = "";
- while (true)
- {
- string fileDataLine;
- fileDataLine = sr.ReadLine();
- if (fileDataLine == null)
- {
- break;
- }
- if (csvDataLine == "")
- {
- csvDataLine = fileDataLine;//GetDeleteQuotaDataLine(fileDataLine);
- }
- else
- {
- csvDataLine += "\r\n" + fileDataLine;//GetDeleteQuotaDataLine(fileDataLine);
- }
- //如果包含偶数个引号,说明该行数据中出现回车符或包含逗号
- if (!IfOddQuota(csvDataLine))
- {
- AddNewDataLine(csvDataLine);
- csvDataLine = "";
- }
- }
- sr.Close();
- //数据行出现奇数个引号
- if (csvDataLine.Length > 0)
- {
- throw new Exception("CSV文件的格式有错误");
- }
- }
- /// <summary>
- /// 获取两个连续引号变成单个引号的数据行
- /// </summary>
- /// <param name="fileDataLine">文件数据行</param>
- /// <returns></returns>
- private string GetDeleteQuotaDataLine(string fileDataLine)
- {
- return fileDataLine.Replace("\"\"", "\"");
- }
- /// <summary>
- /// 判断字符串是否包含奇数个引号
- /// </summary>
- /// <param name="dataLine">数据行</param>
- /// <returns>为奇数时,返回为真;否则返回为假</returns>
- private bool IfOddQuota(string dataLine)
- {
- int quotaCount;
- bool oddQuota;
- quotaCount = 0;
- for (int i = 0; i < dataLine.Length; i++)
- {
- if (dataLine[i] == '\"')
- {
- quotaCount++;
- }
- }
- oddQuota = false;
- if (quotaCount % 2 == 1)
- {
- oddQuota = true;
- }
- return oddQuota;
- }
- /// <summary>
- /// 判断是否以奇数个引号开始
- /// </summary>
- /// <param name="dataCell"></param>
- /// <returns></returns>
- private bool IfOddStartQuota(string dataCell)
- {
- int quotaCount;
- bool oddQuota;
- quotaCount = 0;
- for (int i = 0; i < dataCell.Length; i++)
- {
- if (dataCell[i] == '\"')
- {
- quotaCount++;
- }
- else
- {
- break;
- }
- }
- oddQuota = false;
- if (quotaCount % 2 == 1)
- {
- oddQuota = true;
- }
- return oddQuota;
- }
- /// <summary>
- /// 判断是否以奇数个引号结尾
- /// </summary>
- /// <param name="dataCell"></param>
- /// <returns></returns>
- private bool IfOddEndQuota(string dataCell)
- {
- int quotaCount;
- bool oddQuota;
- quotaCount = 0;
- for (int i = dataCell.Length - 1; i >= 0; i--)
- {
- if (dataCell[i] == '\"')
- {
- quotaCount++;
- }
- else
- {
- break;
- }
- }
- oddQuota = false;
- if (quotaCount % 2 == 1)
- {
- oddQuota = true;
- }
- return oddQuota;
- }
- /// <summary>
- /// 加入新的数据行
- /// </summary>
- /// <param name="newDataLine">新的数据行</param>
- private void AddNewDataLine(string newDataLine)
- {
- //System.Diagnostics.Debug.WriteLine("NewLine:" + newDataLine);
- ////return;
- ArrayList colAL = new ArrayList();
- string[] dataArray = newDataLine.Split(',');
- bool oddStartQuota; //是否以奇数个引号开始
- string cellData;
- oddStartQuota = false;
- cellData = "";
- for (int i = 0; i < dataArray.Length; i++)
- {
- if (oddStartQuota)
- {
- //因为前面用逗号分割,所以要加上逗号
- cellData += "," + dataArray[i];
- //是否以奇数个引号结尾
- if (IfOddEndQuota(dataArray[i]))
- {
- colAL.Add(GetHandleData(cellData));
- oddStartQuota = false;
- continue;
- }
- }
- else
- {
- //是否以奇数个引号开始
- if (IfOddStartQuota(dataArray[i]))
- {
- //是否以奇数个引号结尾,不能是一个双引号,并且不是奇数个引号
- if (IfOddEndQuota(dataArray[i]) && dataArray[i].Length > 2 && !IfOddQuota(dataArray[i]))
- {
- colAL.Add(GetHandleData(dataArray[i]));
- oddStartQuota = false;
- continue;
- }
- else
- {
- oddStartQuota = true;
- cellData = dataArray[i];
- continue;
- }
- }
- else
- {
- colAL.Add(GetHandleData(dataArray[i]));
- }
- }
- }
- if (oddStartQuota)
- {
- throw new Exception("数据格式有问题");
- }
- this.rowAL.Add(colAL);
- }
- /// <summary>
- /// 去掉格子的首尾引号,把双引号变成单引号
- /// </summary>
- /// <param name="fileCellData"></param>
- /// <returns></returns>
- private string GetHandleData(string fileCellData)
- {
- if (fileCellData == "")
- {
- return "";
- }
- if (IfOddStartQuota(fileCellData))
- {
- if (IfOddEndQuota(fileCellData))
- {
- return fileCellData.Substring(1, fileCellData.Length - 2).Replace("\"\"", "\""); //去掉首尾引号,然后把双引号变成单引号
- }
- else
- {
- throw new Exception("数据引号无法匹配" + fileCellData);
- }
- }
- else
- {
- //考虑形如"" """" """"""
- if (fileCellData.Length > 2 && fileCellData[0] == '\"')
- {
- fileCellData = fileCellData.Substring(1, fileCellData.Length - 2).Replace("\"\"", "\""); //去掉首尾引号,然后把双引号变成单引号
- }
- }
- return fileCellData;
- }
- }
- }
|