C#读取Excel导出的CSV文件

有时候我们在项目中需要填写一些配置,通常来说用excel会比较方便。那么这些数据在直接放到项目中使用的时候,可以通过导出csv文件来使用。这里便是一个自己封装的读取csv文件的代码。对特殊字符已经进行了识别,兼容。

完整代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Jing
{
    public class CSVFile
    {
        List<string[]> _data = new List<string[]>();

        /// <summary>
        /// 数据
        /// </summary>
        public string[][] Data
        {
            get { return _data.ToArray(); }
        }

        int _rowCount = 0;

        /// <summary>
        /// 行数
        /// </summary>
        public int RowCount
        {
            get { return _rowCount; }
        }

        int _colCount = 0;

        /// <summary>
        /// 列数
        /// </summary>
        public int ColCount
        {
            get { return _colCount; }
        }

        /// <summary>
        /// 通过数据生成
        /// </summary>
        /// <param name="data"></param>
        public CSVFile(byte[] data, Encoding encoding)
        {            
            var content = encoding.GetString(data);
            string[] rows = content.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            ParseRows(rows);
        }

        public CSVFile(string path)
        {
            System.Text.Encoding encoding = GetEncoding(path);
            string[] rows = File.ReadAllLines(path, encoding);
            ParseRows(rows);
        }       
        
        void ParseRows(string[] rows)
        {
            for (int i = 0; i < rows.Length; i++)
            {
                var cols = GetCols(rows[i]);
                if (null != cols)
                {
                    _data.Add(cols.ToArray());
                }
            }

            _rowCount = _data.Count;
            if (_rowCount > 0)
            {
                _colCount = _data[0].Length;
            }
        }

        /// <summary>
        /// 得到表格的值
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        public string GetValue(int row, int col)
        {
            return _data[row][col];
        }

        /// <summary>
        /// 分割一行字符串中的列
        /// </summary>
        /// <param name="rowContent"></param>
        /// <returns></returns>
        List<string> GetCols(string rowContent)
        {
            //引号
            const char QUOTATION_MARKS = '"';
            //逗号
            const char COMMA = ',';

            List<string> cols = new List<string>();
            //分割标记(同时也是一列字符串的第一个字符的索引)
            int splitMark = 0;
            int charIdx = 0;
            bool isSpecial = false;
            while (charIdx < rowContent.Length)
            {
                char c = rowContent[charIdx];
                int nextIdx = charIdx + 1;

                if (charIdx == splitMark)
                {                    
                    if (c == QUOTATION_MARKS)
                    {
                        isSpecial = true;                        
                    }
                    else
                    {
                        isSpecial = false;
                        if(nextIdx == rowContent.Length)
                        {
                            //结束符
                            string colContent = rowContent.Substring(splitMark);
                            cols.Add(colContent);
                            break;
                        }
                    }
                }
                else
                {
                    if(isSpecial)
                    {
                        //处理含有特殊字符串的内容
                        if (c == QUOTATION_MARKS)
                        {                            
                            if (nextIdx == rowContent.Length)
                            {
                                //结束符
                                string colContent = rowContent.Substring(splitMark + 1, charIdx - splitMark - 1);
                                colContent = colContent.Replace("\"\"", "\"");
                                cols.Add(colContent);                                
                                //跳过下一个引号
                                charIdx++;
                            }
                            else
                            {
                                char nextC = rowContent[nextIdx];
                                if(nextC == QUOTATION_MARKS)
                                {
                                    //跳过双引号
                                    charIdx++;
                                }
                                else if(nextC == COMMA)
                                {
                                    //分割符
                                    string colContent = rowContent.Substring(splitMark + 1, charIdx - splitMark - 1);
                                    colContent = colContent.Replace("\"\"", "\"");
                                    cols.Add(colContent);
                                    charIdx++;
                                    splitMark = nextIdx + 1;
                                }
                            }
                        }
                    }
                    else
                    {
                        //处理普通字符串的内容
                        if(c == COMMA)
                        {
                            //分割符
                            string colContent = rowContent.Substring(splitMark, charIdx - splitMark);
                            cols.Add(colContent);
                            splitMark = charIdx + 1;                            
                        }

                        if (nextIdx == rowContent.Length)
                        {
                            //结束符
                            string colContent = rowContent.Substring(splitMark);
                            cols.Add(colContent);
                            break;
                        }
                    }
                }

                charIdx++;
            }

            return cols;
        }

        System.Text.Encoding GetEncoding(string FILE_NAME)
        {
            FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
            System.Text.Encoding r = GetEncoding(fs);
            fs.Close();
            return r;
        }


        System.Text.Encoding GetEncoding(FileStream fs)
        {
            BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);
            byte[] ss = r.ReadBytes(3);
            r.Close();
            //编码类型 Coding=编码类型.ASCII;   
            if (ss[0] >= 0xEF)
            {
                if (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF)
                {
                    return System.Text.Encoding.UTF8;
                }
                else if (ss[0] == 0xFE && ss[1] == 0xFF)
                {
                    return System.Text.Encoding.BigEndianUnicode;
                }
                else if (ss[0] == 0xFF && ss[1] == 0xFE)
                {
                    return System.Text.Encoding.Unicode;
                }
                else
                {
                    return System.Text.Encoding.Default;
                }
            }
            else
            {
                return System.Text.Encoding.Default;
            }
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容