C#按Excel 规则读取、写入CSV文件,放入DataTable,再读取、写入dataGridView内。包含解析转义字符,首行判断,转换完成信号等。

     CSV文件有很多规则,主要是处理逗号(,)和双引号(")的方法不同,这里按Excel 规则解析转义字符。主要规则为:

           1.有逗号(,)或开头为双引号(")的字符串在保存时前后加双引号,

           2.若字符串前后加双引号,则将字符串内的双引号(如有)替换为两个双引号。

    读取csv文件后放在DataTable内方便处理数据,可将csv文件首行作为DataTable列表头,也可自动生产列表头,完成后返回true。读取dataGridView后放在DataTable内方便处理数据,可将cdataGridView列表头作为首行,也可忽视列表头,完成后返回true。

     加了文件打开的异常报警,主要分为四个函数模块:
        1.从csv文件读取数据到DataTable
        public static DataTable ReadDataFromCsv(string file, bool isFirst, out bool isok)

        其中string file为csv文件名,bool isFirst为是否将首行设为列标题,out bool isok为读取成功标志。返回DataTable表(读取失败亦返回表)。

        2.从DataGridView内读取数据到DataTable
        public static DataTable GetDgvToTable(DataGridView dgv, bool isFirst, out bool isok)       

        其中DataGridView dgv为DataGridView控件文件名,bool isFirst为是否将列标题设为首行,out bool isok为读取成功标志。返回DataTable表(读取失败亦返回表)。

        3.从DataTable读取数据写入到csv文件
        public static bool WriteDataToCsv(DataTable dt, string fullPath, bool isFirst)

        其中DataTable dt为DataTable表名,bool isFirst为是否将首行设为列标题。返回写入成功标志。

        4.分析csv文件行内容(整行作为一个字符串),并按规则解析,返回字符串集合。

        private static List<string> ReadValue(string line)

      其中string line为要分割解析的字符串,返回 List<string>字符串列表

参考C#读取CSV文件_魏甲鑫的博客-CSDN博客_c#读取 csv解析思路。

参考C# CSV文件操作_000伊凡000的博客-CSDN博客_c# csv文件读取和写入思路。

直接上代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 数据
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {

            bool isok;
            DataTable dt = ReadDataFromCsv(@"../../115.CSV", true, out isok);
            if (isok)
            {
                dataGridView1.DataSource = dt.DefaultView;
            }


        }
        private void button2_Click(object sender, EventArgs e)
        {
            bool isok;
            DataTable dt2 = GetDgvToTable(dataGridView1, true, out isok);
            if (isok)
            {
                dataGridView2.DataSource = dt2;
            }
            isok = WriteDataToCsv(dt2, @"../../1115.CSV", true);


        }

        //string file为csv文件名,bool isFirst为是否将首行设为列标题,out bool isok为读取成功标志。返回DataTable表(读取失败亦返回表)。
        public static DataTable ReadDataFromCsv(string file, bool isFirst, out bool isok)
        {
            DataTable dt = null;

            if (File.Exists(file))
            {
                dt = new DataTable();
                FileStream fs = null;
                StreamReader sr = null;
                try
                {
                    fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Read);
                    sr = new StreamReader(fs, Encoding.Default);
                }
                catch
                {
                    MessageBox.Show(file + "文件正在使用或打不开");
                    isok = false;
                    return dt;
                }
                try
                {
                    string head = sr.ReadLine();
                    List<string> valueList = ReadValue(head);

                    if (isFirst == true)//列表题使用首行
                    {
                        for (int i = 0; i < valueList.Count; i++)
                        {
                            dt.Columns.Add(valueList[i], typeof(string));//列表题使用首行
                        }
                    }
                    else
                    {
                        for (int i = 0; i < valueList.Count; i++)
                        {
                            dt.Columns.Add("Columns" + i.ToString(), typeof(string));//列表题自动生成

                        }
                        DataRow drHead = dt.NewRow();
                        for (int n = 0; n < valueList.Count; n++)
                        {
                            drHead[n] = valueList[n];         //添加首行
                        }
                        dt.Rows.Add(drHead);
                    }

                    while (!sr.EndOfStream)
                    {
                        #region ==循环读取文件==
                        string lineStr = sr.ReadLine();
                        if (lineStr == null || lineStr.Length == 0)
                            continue;
                        List<string> valueList2 = ReadValue(lineStr);
                        #region ==添加行数据==
                        DataRow dr = dt.NewRow();
                        for (int i = 0; i < valueList2.Count; i++)
                        {
                            dr[i] = valueList2[i];
                        }
                        dt.Rows.Add(dr);
                        #endregion
                    }
                }
                catch
                {
                    MessageBox.Show(file + "文件格式不对或内容为空");
                    isok = false;
                    return dt;
                }


                fs.Close();
                sr.Close();
                isok = true;
                        #endregion
            }
            else
            {
                dt = new DataTable();
                MessageBox.Show(file + "文件不存在");
                isok = false;
            }

            return dt;
        }
        //分割解析字符串,string line为要分割解析的字符串,返回 List<string>字符串列表
        private static List<string> ReadValue(string line)
        {
            var resList = new List<List<string>>();
            var valueList = new List<string>();
            var datas = line.Split(',');
            var queue = new Queue<string>();
            foreach (var data in datas)
            {
                if (queue.Count <= 0)
                {
                    if (data.StartsWith("\""))
                    {
                        if (data.EndsWith("\"") && !data.EndsWith("\"\"") && data.Length >= 2)
                            valueList.Add(DelESC(data.Substring(1, data.Length - 2)));
                        else
                            queue.Enqueue(data);
                    }
                    else
                    {
                        valueList.Add(data);
                    }
                }
                else
                {
                    if (data.EndsWith("\"") && !data.EndsWith("\"\""))
                    {
                        queue.Enqueue(data);
                        valueList.Add(DelESC(GetStringByQueue(queue)));
                        queue.Clear();
                    }

                    else if ((data.EndsWith("\"\"\"")) && !data.EndsWith("\"\"\"\""))
                    {
                        queue.Enqueue(data);
                        valueList.Add(DelESC(GetStringByQueue(queue)));
                        queue.Clear();
                    }


                    else
                    {
                        queue.Enqueue(data);
                    }
                }

                resList.Add(valueList);
            }
            return valueList;
        }

        //从队列中拼接字符串并删去前后的<">
        private static string GetStringByQueue(Queue<string> queue)
        {
            var str = "";
            if (queue.Count <= 0)
                return "";
            str += queue.Dequeue();
            for (var i = 0; queue.Count > 0; i++) str += "," + queue.Dequeue();
            str = str.Substring(1, str.Length - 2);
            return str;
        }

        //删去字符串中的转义,表格导出的csv中只有"被转义为""
        private static string DelESC(string str)
        {
            var count = 0;
            var cs = new char[str.Length];
            for (var i = 0; i < str.Length; i++, count++)
            {
                if (str[i] == '\"') i++;
                cs[count] = str[i];
            }

            return new string(cs, 0, count);
        }

        //DataTable dt为DataTable表名,bool isFirst为是否将首行设为列标题。返回写入成功标志。
        public static bool WriteDataToCsv(DataTable dt, string fullPath, bool isFirst)
        {
            FileStream fs = null;
            StreamWriter sw = null;
            try
            {
                FileInfo fi = new FileInfo(fullPath);
                if (!fi.Directory.Exists)
                {
                    fi.Directory.Create();
                }
                fs = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
                sw = new StreamWriter(fs, Encoding.UTF8);

            }
            catch
            {
                MessageBox.Show(fullPath + "文件正在使用或打不开");
                return false;
            }
            string data = "";
            if (isFirst == true)//列表题作为首行
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    string str = dt.Columns[i].ColumnName.ToString();

                    if (str.Contains(',') || str.StartsWith("\"")) //含逗号 开头双引号 的需要放到引号中
                    {
                        str = str.Replace("\"", "\"\"");//替换英文双引号 英文双引号需要换成两个双引号
                        str = string.Format("\"{0}\"", str);
                    }
                    data += str;
                    if (i < dt.Columns.Count - 1)
                    {
                        data += ",";
                    }
                }
                sw.WriteLine(data);
            }

            //写出各行数据
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                data = "";
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    string str = dt.Rows[i][j].ToString();
                    if (str.Contains(',') || str.StartsWith("\"")) //含逗号 开头双引号 的需要放到引号中
                    {
                        str = str.Replace("\"", "\"\"");//替换英文双引号 英文双引号需要换成两个双引号
                        str = string.Format("\"{0}\"", str);
                    }
                    data += str;
                    if (j < dt.Columns.Count - 1)
                    {
                        data += ",";
                    }
                }
                sw.WriteLine(data);
            }
            sw.Close();
            fs.Close();
            return true;
        }
        //DataGridView dgv为DataGridView控件文件名,bool isFirst为是否将列标题设为首行,out bool isok为读取成功标志。返回DataTable表(读取失败亦返回表)。
        public static DataTable GetDgvToTable(DataGridView dgv, bool isFirst, out bool isok)
        {
            DataTable dt = new DataTable();
            if (dgv.RowCount == 0)//判断DataGridView控件是否为空
            {
                MessageBox.Show(dgv.Name + "为空,不能导出");
                isok = false;
                return dt;
            }
            int count1 = 0;
            if (isFirst == true)//列表题作为首行
            {
                // 列强制转换
                for (int count = 0; count < dgv.Columns.Count; count++)
                {
                    DataColumn dc = new DataColumn(dgv.Columns[count].Name.ToString());
                    dt.Columns.Add(dc);
                    count1 = 0;
                }
            }

            else  //列表第一行作为首行
            {
                // 列强制转换
                for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
                {
                    DataColumn dc = new DataColumn(Convert.ToString(dgv.Rows[0].Cells[countsub].Value));
                    dt.Columns.Add(dc);
                    count1 = 1;
                }
            }

            // 循环行
            for (int count = count1; count < dgv.Rows.Count; count++)
            {
                DataRow dr = dt.NewRow();
                for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
                {
                    dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);
                }
                dt.Rows.Add(dr);
            }

            isok = true;
            return dt;
        }
    }
}

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值