C# 自定义标准 读写CSV文件

CSV文件格式标准:

  1. 编码方式:UTF-8
  2. 行分割符为换行符(\r\n); 列分割符为英文逗号(,);
  3. 内容行 第一行为标题行(即列名);
  4. 约定特殊字符处理标准:

数据源文本

目标文本

英文逗号(,)

英文逗号(,)

出现左侧一种或多中情况时,在文本两侧加上英文冒号(“ )

英文冒号(“ )

替换成两个英文冒号(“”)

换行符(\n)

换行符(\n)

回车符(\r)

回车符(\r)

回车换行符(\r\n)

替换成(\r/\n)

操作示例:

  private DataTable GetData()
        {
            DataTable dta = new DataTable();
            dta.Columns.Add("Code");
            dta.Columns.Add("Name");
            dta.Columns.Add("Address");
            dta.Rows.Add("1", "正常", "中国北京");
            dta.Rows.Add("1", "逗号", "中国,北京");
            dta.Rows.Add("1", "换行", "中国\n北京");
            dta.Rows.Add("1", "回车换行", "中国\r\n北京");
            dta.Rows.Add("1", "逗号换行", "中,国北\n京");
            dta.Rows.Add("1", "1个单引号", "中国'北京");
            dta.Rows.Add("1", "2个单引号", "中国'北'京");
            dta.Rows.Add("1", "1个双引号", "中国\"北京");
            dta.Rows.Add("1", "2个双引号", "中国\"北\"京");
            dta.Rows.Add("1", "1个单双引号", "中国'北\"京");
            return dta;
        }

        private void WCsv_Loaded(object sender, RoutedEventArgs e)
        {
            string path = $@"C:\Users\Administrator\Desktop\ABC.csv";
            string path2 = $@"C:\Users\Administrator\Desktop\ABC2.csv";
            DataTable dta = GetData();
            string errInfo;
            //把数据集写到文件1
            bool isOk =FuncCsv. CsvWrite(dta, path, out errInfo);
            //读取文件1
            DataTable dt2 = FuncCsv.CsvRead(path, out errInfo);
            //把文件1的数据写到文件2,比较文件是否一致
            bool isOk2= FuncCsv.CsvWrite(dt2, path2, out errInfo);
        }

自定义类:

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

namespace Wpfjsj
{
    /// 
    /// CSV自定义类
    /// 
   public static class FuncCsv
    {
        private static readonly object Obj = new object();
        /// 
        /// 把数据集写到CSV文件
        /// 
        /// 数据集
        /// 文件路径
        /// 异常信息
        /// 编码方式 默认为空(UFT-8)
        /// 是否包含标题行(列名) 默认包含
        /// 返回值 写入是否成功
        public static bool CsvWrite(DataTable dt, string path, out string errInfo, Encoding en = null, bool isConHeader = true)
        {
            lock (Obj)
            {
                try
                {
                    errInfo = "";
                    //以半角逗号(即,)作分隔符,列为空也要表达其存在。  
                    //列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。  
                    //列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。  
                    StringBuilder sb = new StringBuilder();
                    if (isConHeader)
                    {
                        for (int m = 0; m < dt.Columns.Count; m++)
                        {
                            sb.Append(dt.Columns[m].ColumnName);
                            if (m != dt.Columns.Count - 1)
                                sb.Append(",");
                        }
                        sb.Append("\r\n");
                    }
                    foreach (DataRow row in dt.Rows)
                    {
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {
                            var colum = dt.Columns[i];
                            if (i != 0) sb.Append(",");
                            string str = row[colum].ToString();
                            sb.Append(colum.DataType == typeof(string) ? ConvStr_CsvWrite(str) : str);
                        }
                        sb.Append("\r\n");
                    }

                    StreamWriter sw = new StreamWriter(path, false, en ?? Encoding.UTF8);
                    sw.Write(sb);
                    sw.Flush();
                    sw.Close();
                    return true;
                }
                catch (Exception ex)
                {
                    errInfo = ex.Message;
                    return false;
                }
            }
        }

        private static readonly object Obj1 = new object();
        /// 
        /// 读取CSV文件内容到数据集
        /// 
        /// 文件路径
        /// 异常信息
        /// 编码方式 默认为空(UFT-8)
        /// 文件内容是否包含标题行(列名),默认包含
        /// 返回的数据集
        public static DataTable CsvRead(string path, out string errInfo, Encoding en = null, bool isConHeader = true)
        {
            lock (Obj1)
            {
                errInfo = "";
                DataTable dt = new DataTable();
                try
                {
                    //读取文件
                    StreamReader sr = new StreamReader(path, en ?? Encoding.UTF8);
                    string result = sr.ReadToEnd();
                    sr.Close();
                    //解析文件
                    int index = 0;
                    foreach (string content in result.Split(new[] {"\r\n"}, StringSplitOptions.None))
                    {
                        if (string.IsNullOrWhiteSpace(content)) continue;
                        string[] strCols = StrToStrArray(content);
                        if (index == 0)
                        {
                            if (isConHeader)
                            {
                                foreach (string str in strCols)
                                    dt.Columns.Add(str);
                                index++;
                                continue;
                            }
                            //自定义标题
                            for (int m = 1; m <= strCols.Length; m++)
                                dt.Columns.Add($"Col{m}");
                            index = 1;
                        }
                        dt.Rows.Add(strCols);
                    }
                }
                catch (Exception ex)
                {
                    errInfo = ex.Message;
                }
                return dt;
            }
        }

        private static string[] StrToStrArray(string strLine)
        {
            string[] strFirsts = strLine.Split(',');
            List list = new List();
            StringBuilder sbCombie = new StringBuilder();
            foreach (string str in strFirsts)
            {
                int indexOneFirst = str.IndexOf('\"');
                //常规字符串
                if (sbCombie.Length == 0 && indexOneFirst < 0)
                {
                    list.Add(str);
                    continue;
                }

                //字符串末尾 冒号连续出现的次数为奇数 则字符串结束
                int count = 0;
                for (int n = str.Length - 1; n >= 0; n--)
                {
                    if (str[n] == '\"')
                        count++;
                    else
                        break;
                }

                //源字符串带冒号 不带逗号
                if (sbCombie.Length == 0 && indexOneFirst == 0 && count % 2 == 1)
                {
                    list.Add(ConvStr_CsvRead(str));
                    continue;
                }

                if (count % 2 == 0)
                {
                    sbCombie.Append($"{str},");
                }
                else
                {
                    sbCombie.Append(str);
                    list.Add(ConvStr_CsvRead(sbCombie.ToString()));
                    sbCombie.Clear();
                }
            }
            return list.ToArray();
        }

        private static string ConvStr_CsvRead(string str)
        {
            if (str.Contains('\"'))
            {
                str = str.Replace("\r/\n", "\r\n").Replace("\"\"", "\"");
                return str.Substring(1, str.Length - 2);
            }
            return str;
        }

        private static string ConvStr_CsvWrite(string str)
        {
            if (str.Contains(',') || str.Contains('\n') || str.Contains('\r') || str.Contains('"'))
                return $"\"{str.Replace("\r\n", "\r/\n").Replace("\"", "\"\"")}\"";
            return str;
        }
    }
}

 

你可能感兴趣的:(C#,CSV读取,C#,CSV标准)