C# 读取 CSV 文件,简易实现

经常用到csv文件,一直用odbc进行读取,但是在unicode编码的时候读取不正确,有时候就算是ANSI编码,如一列数据混编,读取也不正确。不清楚是不是个人电脑的问题。只好自己写个来实现简单的读取,解析含","及"""号CSV文件。

更新1:使用中发现有些软件生存csv文件时,所有数据默认带有"",以前代码处理带引号空字段数据不正确。

    代码如下,默认用UTF8编码,一次性读取整个CSV文件,若谁试用了此段代码,有问题请反馈给我,谢谢。

        /// <summary>

        /// 读取csv文件到DataTable

        /// </summary>

        /// <param name="filepath"></param>

        /// <returns></returns>

        static private DataTable ReadCsv(string filepath)

        {

            DataTable dt = new DataTable("NewTable");

            DataRow row;



            string[] lines = File.ReadAllLines(filepath, Encoding.UTF8);

            string[] head = lines[0].Split(',');

            int cnt = head.Length;

            for (int i = 0; i < cnt; i++)

            {

                dt.Columns.Add(head[i]);

            }

            for (int i = 0; i < lines.Length; i++)

            {

                lines[i].Trim();

                if ((string.IsNullOrWhiteSpace(lines[i])))

                {

                    continue;

                }

                try

                {

                    row = dt.NewRow();

                    row.ItemArray = GetRow(lines[i], cnt);

                    dt.Rows.Add(row);

                }

                catch { }

            }

            return dt;

        }

        /// <summary>

        /// 解析字符串 获取 该行的数据 已经处理,及"号

        /// </summary>

        /// <param name="line">该行的内容</param>

        /// <param name="cnt">总的条目数</param>

        /// <returns></returns>

        static private string[] GetRow(string line, int cnt)

        {

            //line = line.Replace("\"\"", "\""); //若空数据加引号替换不正确

            string[] strs = line.Split(',');

            if (strs.Length == cnt)

            {

                return RemoveQuotes(strs);

            }

            List<string> list = new List<string>();

            int n = 0, begin = 0;

            bool flag = false;



            for (int i = 0; i < strs.Length; i++)

            {



                //没有引号 或者 中间有引号 直接添加

                if (strs[i].IndexOf("\"") == -1

                    || (flag == false && strs[i][0] != '\"'))

                {

                    list.Add(strs[i]);

                    continue;

                }

                //其实有引号,但该段没有,号,直接添加

                n = 0;

                foreach (char ch in strs[i])

                {

                    if (ch == '\"')

                    {

                        n++;

                    }

                }

                if (n % 2 == 0)

                {

                    list.Add(strs[i]);

                    continue;

                }

                //该段有引号 有 ,号,下一段增加后添加

                flag = true;

                begin = i;

                i++;

                for (i = begin + 1; i < strs.Length; i++)

                {

                    foreach (char ch in strs[i])

                    {

                        if (ch == '\"')

                        {

                            n++;

                        }

                    }

                    if (strs[i][strs[i].Length - 1] == '\"' && n % 2 == 0)

                    {

                        StringBuilder sb = new StringBuilder();

                        for (; begin <= i; begin++)

                        {

                            sb.Append(strs[begin]);

                            if (begin != i)

                            {

                                sb.Append(",");

                            }

                        }

                        list.Add(sb.ToString());

                        break;

                    }

                }

            }

            return RemoveQuotes(list.ToArray());

        }

        /// <summary>

        /// 将解析的数据 去除多余的引号

        /// </summary>

        /// <param name="strs"></param>

        /// <returns></returns>

        static string[] RemoveQuotes(string[] strs)

        {

            for (int i = 0; i < strs.Length; i++)

            {

                //若该项数据为空 但csv文件中加上双引号

                if (strs[i] == "\"\"")

                {

                    strs[i] = "";

                    continue;

                }

                //若该项数据头和尾加上引号

                if (strs[i].Length > 2 && strs[i][0] == '\"' && strs[i][strs[i].Length - 1] == '\"')

                {

                    strs[i] = strs[i].Substring(1, strs[i].Length - 2);

                }

                //若该项数据中间有引号

                strs[i] = strs[i].Replace("\"\"", "\"");

            }

            return strs;

        }
 

你可能感兴趣的:(csv)