C#读取csv格式文件的方法
本文实例讲述了C#读取csv格式文件的方法。分享给大家供大家参考。具体实现方法如下:
一、CSV文件规则
1开头是不留空,以行为单位。
2可含或不含列名,含列名则居文件第一行。
3一行数据不跨行,无空行。
4以半角逗号(即,)作分隔符,列为空也要表达其存在。
5列内容如存在半角逗号(即,)则用半角引号(即',')将该字段值包含起来。
6列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
7文件读写时引号,逗号操作规则互逆。
8内码格式不限,可为ASCII、Unicode或者其他。
9不支持特殊字符
二、C#读取csv文件的方法
//读CSV文件类,读取指定的CSV文件,可以导出DataTable publicclassCsvStreamReader { privateArrayListrowAL; //行链表,CSV文件的每一行就是一个链 privatestringfileName; //文件名 privateEncodingencoding; //编码 publicCsvStreamReader() { this.rowAL=newArrayList(); this.fileName=""; this.encoding=Encoding.Default; } ///<summary> /// ///</summary> ///<paramname="fileName">文件名,包括文件路径</param> publicCsvStreamReader(stringfileName) { this.rowAL=newArrayList(); this.fileName=fileName; this.encoding=Encoding.Default; LoadCsvFile(); } ///<summary> /// ///</summary> ///<paramname="fileName">文件名,包括文件路径</param> ///<paramname="encoding">文件编码</param> publicCsvStreamReader(stringfileName,Encodingencoding) { this.rowAL=newArrayList(); this.fileName=fileName; this.encoding=encoding; LoadCsvFile(); } ///<summary> ///文件名,包括文件路径 ///</summary> publicstringFileName { set { this.fileName=value; LoadCsvFile(); } } ///<summary> ///文件编码 ///</summary> publicEncodingFileEncoding { set { this.encoding=value; } } ///<summary> ///获取行数 ///</summary> publicintRowCount { get { returnthis.rowAL.Count; } } ///<summary> ///获取列数 ///</summary> publicintColCount { get { intmaxCol; maxCol=0; for(inti=0;i<this.rowAL.Count;i++) { ArrayListcolAL=(ArrayList)this.rowAL[i]; maxCol=(maxCol>colAL.Count)?maxCol:colAL.Count; } returnmaxCol; } }
///<summary> ///获取某行某列的数据 ///row:行,row=1代表第一行 ///col:列,col=1代表第一列 ///</summary> publicstringthis[introw,intcol] { get { //数据有效性验证 CheckRowValid(row); CheckColValid(col); ArrayListcolAL=(ArrayList)this.rowAL[row-1]; //如果请求列数据大于当前行的列时,返回空值 if(colAL.Count<col) { return""; } returncolAL[col-1].ToString(); } }
///<summary> ///根据最小行,最大行,最小列,最大列,来生成一个DataTable类型的数据 ///行等于1代表第一行 ///列等于1代表第一列 ///maxrow:-1代表最大行 ///maxcol:-1代表最大列 ///</summary> publicDataTablethis[intminRow,intmaxRow,intminCol,intmaxCol] { get { //数据有效性验证 CheckRowValid(minRow); CheckMaxRowValid(maxRow); CheckColValid(minCol); CheckMaxColValid(maxCol); if(maxRow==-1) { maxRow=RowCount; } if(maxCol==-1) { maxCol=ColCount; } if(maxRow<minRow) { thrownewException("最大行数不能小于最小行数"); } if(maxCol<minCol) { thrownewException("最大列数不能小于最小列数"); } DataTablecsvDT=newDataTable(); inti; intcol; introw; //增加列 for(i=minCol;i<=maxCol;i++) { csvDT.Columns.Add(i.ToString()); } for(row=minRow;row<=maxRow;row++) { DataRowcsvDR=csvDT.NewRow(); i=0; for(col=minCol;col<=maxCol;col++) { csvDR[i]=this[row,col]; i++; } csvDT.Rows.Add(csvDR); } returncsvDT; } }
///<summary> ///检查行数是否是有效的 ///</summary> ///<paramname="col"></param> privatevoidCheckRowValid(introw) { if(row<=0) { thrownewException("行数不能小于0"); } if(row>RowCount) { thrownewException("没有当前行的数据"); } } ///<summary> ///检查最大行数是否是有效的 ///</summary> ///<paramname="col"></param> privatevoidCheckMaxRowValid(intmaxRow) { if(maxRow<=0&&maxRow!=-1) { thrownewException("行数不能等于0或小于-1"); } if(maxRow>RowCount) { thrownewException("没有当前行的数据"); } } ///<summary> ///检查列数是否是有效的 ///</summary> ///<paramname="col"></param> privatevoidCheckColValid(intcol) { if(col<=0) { thrownewException("列数不能小于0"); } if(col>ColCount) { thrownewException("没有当前列的数据"); } } ///<summary> ///检查检查最大列数是否是有效的 ///</summary> ///<paramname="col"></param> privatevoidCheckMaxColValid(intmaxCol) { if(maxCol<=0&&maxCol!=-1) { thrownewException("列数不能等于0或小于-1"); } if(maxCol>ColCount) { thrownewException("没有当前列的数据"); } } ///<summary> ///载入CSV文件 ///</summary> privatevoidLoadCsvFile() { //对数据的有效性进行验证 if(this.fileName==null) { thrownewException("请指定要载入的CSV文件名"); } elseif(!File.Exists(this.fileName)) { thrownewException("指定的CSV文件不存在"); } else { } if(this.encoding==null) { this.encoding=Encoding.Default; } StreamReadersr=newStreamReader(this.fileName,this.encoding); stringcsvDataLine; csvDataLine=""; while(true) { stringfileDataLine; 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) { thrownewException("CSV文件的格式有错误"); } } ///<summary> ///获取两个连续引号变成单个引号的数据行 ///</summary> ///<paramname="fileDataLine">文件数据行</param> ///<returns></returns> privatestringGetDeleteQuotaDataLine(stringfileDataLine) { returnfileDataLine.Replace("\\"\\"","\\""); } ///<summary> ///判断字符串是否包含奇数个引号 ///</summary> ///<paramname="dataLine">数据行</param> ///<returns>为奇数时,返回为真;否则返回为假</returns> privateboolIfOddQuota(stringdataLine) { intquotaCount; booloddQuota; quotaCount=0; for(inti=0;i<dataLine.Length;i++) { if(dataLine[i]=='\\"') { quotaCount++; } } oddQuota=false; if(quotaCount%2==1) { oddQuota=true; } returnoddQuota; } ///<summary> ///判断是否以奇数个引号开始 ///</summary> ///<paramname="dataCell"></param> ///<returns></returns> privateboolIfOddStartQuota(stringdataCell) { intquotaCount; booloddQuota; quotaCount=0; for(inti=0;i<dataCell.Length;i++) { if(dataCell[i]=='\\"') { quotaCount++; } else { break; } } oddQuota=false; if(quotaCount%2==1) { oddQuota=true; } returnoddQuota; } ///<summary> ///判断是否以奇数个引号结尾 ///</summary> ///<paramname="dataCell"></param> ///<returns></returns> privateboolIfOddEndQuota(stringdataCell) { intquotaCount; booloddQuota; quotaCount=0; for(inti=dataCell.Length-1;i>=0;i--) { if(dataCell[i]=='\\"') { quotaCount++; } else { break; } } oddQuota=false; if(quotaCount%2==1) { oddQuota=true; } returnoddQuota; } ///<summary> ///加入新的数据行 ///</summary> ///<paramname="newDataLine">新的数据行</param> privatevoidAddNewDataLine(stringnewDataLine) { //System.Diagnostics.Debug.WriteLine("NewLine:"+newDataLine); ////return; ArrayListcolAL=newArrayList(); string[]dataArray=newDataLine.Split(','); booloddStartQuota; //是否以奇数个引号开始 stringcellData; oddStartQuota=false; cellData=""; for(inti=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) { thrownewException("数据格式有问题"); } this.rowAL.Add(colAL); }
///<summary> ///去掉格子的首尾引号,把双引号变成单引号 ///</summary> ///<paramname="fileCellData"></param> ///<returns></returns> privatestringGetHandleData(stringfileCellData) { if(fileCellData=="") { return""; } if(IfOddStartQuota(fileCellData)) { if(IfOddEndQuota(fileCellData)) { returnfileCellData.Substring(1,fileCellData.Length-2).Replace("\\"\\"","\\"");//去掉首尾引号,然后把双引号变成单引号 } else { thrownewException("数据引号无法匹配"+fileCellData); } } else { //考虑形如"" """" """""" if(fileCellData.Length>2&&fileCellData[0]=='\\"') { fileCellData=fileCellData.Substring(1,fileCellData.Length-2).Replace("\\"\\"","\\"");//去掉首尾引号,然后把双引号变成单引号 } } returnfileCellData; } }