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($"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<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;
        }
    }
}

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C是一个广泛使用的计算机编程语言。C语言由贝尔实验室的Dennis Ritchie在20世纪70年代初开发。从那时起,C语言一直是最受欢迎和广泛使用的编程语言之一。 C语言具有直接而简单的语法结构,因此易于学习和使用。它提供了丰富的编程功能和灵活性,使得开发者可以编写高效且可移植的代码。C语言可以用于开发各种应用程序,例如操作系统、编译器、数据库、嵌入式系统和网络应用等。 C语言广泛应用于计算机科学和软件开发领域。它是大多数计算机科学专业学生的必修课程,并且被广泛使用于编程教育和训练中。许多著名的软件和计算机系统,如UNIX操作系统和Linux内核,都是用C语言编写的。 C语言的最大特点之一是它的效率和性能。由于其与硬件之间的密切关系,开发者可以直接访问计算机的底层资源,使得C语言编写的程序速度快且占用内存少。此外,C语言还提供了丰富的库函数和工具,方便开发者进行程序设计和调试。 然而,使用C语言编写程序也存在一些挑战。首先,C语言对细节要求严格,需要程序员注意内存管理和指针操作等细节。其次,C语言没有内置的面向对象特性,需要开发者自己实现;这在某些情况下可能会增加开发的复杂性。 总而言之,C语言是一种功能强大且广泛应用的计算机编程语言。它具有直接而简单的语法结构、高效和可移植性等优点,因此在计算机科学和软件开发领域得到了广泛的应用和认可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值