当前位置: 移动技术网 > IT编程>开发语言>c# > C#读取csv格式文件的方法

C#读取csv格式文件的方法

2019年07月18日  | 移动技术网IT编程  | 我要评论

本文实例讲述了c#读取csv格式文件的方法。分享给大家供大家参考。具体实现方法如下:

一、csv文件规则
 
1 开头是不留空,以行为单位。
2 可含或不含列名,含列名则居文件第一行。
3 一行数据不跨行,无空行。
4 以半角逗号(即,)作分隔符,列为空也要表达其存在。
5 列内容如存在半角逗号(即,)则用半角引号(即',')将该字段值包含起来。
6 列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
7 文件读写时引号,逗号操作规则互逆。
8 内码格式不限,可为 ascii、unicode 或者其他。
9 不支持特殊字符
 
二、c#读取csv文件的方法

复制代码 代码如下:
//读csv文件类,读取指定的csv文件,可以导出datatable
    public class csvstreamreader
    {
        private arraylist rowal;         //行链表,csv文件的每一行就是一个链
        private string filename;        //文件名
        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;
        }
    }

希望本文所述对大家的c#程序设计有所帮助。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网