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

Posted Jia_ShengJie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

    /// <summary>
    /// CSV自定义类
    /// </summary>
   public static class FuncCsv
    
        private static readonly object Obj = new object();
        /// <summary>
        /// 把数据集写到CSV文件
        /// </summary>
        /// <param name="dt">数据集</param>
        /// <param name="path">文件路径</param>
        /// <param name="errInfo">异常信息</param>
        /// <param name="en">编码方式 默认为空(UFT-8)</param>
        /// <param name="isConHeader">是否包含标题行(列名) 默认包含</param>
        /// <returns>返回值 写入是否成功</returns>
        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();
        /// <summary>
        /// 读取CSV文件内容到数据集
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="errInfo">异常信息</param>
        /// <param name="en">编码方式 默认为空(UFT-8)</param>
        /// <param name="isConHeader">文件内容是否包含标题行(列名),默认包含</param>
        /// <returns>返回的数据集</returns>
        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($"Colm");
                            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<string> list = new List<string>();
            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文件读写

(54)C#里简单地读写CSV文件

(54)C#里简单地读写CSV文件

(54)C#里简单地读写CSV文件

R-从 PurpleAir 传感器读取 csv 文件并跳过某些行末尾包含非标准字符的错误位置

python对csv文件的读写操作