欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-02-11 17:18:34
本文实例讲述了c#读取csv格式文件的方法。分享给大家供大家参考。具体实现方法如下: 一、csv文件规则   1 开头是不留空,以行为单位。 2 可含或不...

本文实例讲述了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#程序设计有所帮助。