C# 自定义标准 读写CSV文件
Posted Jia_ShengJie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 自定义标准 读写CSV文件相关的知识,希望对你有一定的参考价值。
CSV文件格式标准:
- 编码方式:UTF-8
- 行分割符为换行符(\\r\\n); 列分割符为英文逗号(,);
- 内容行 第一行为标题行(即列名);
- 约定特殊字符处理标准:
数据源文本 | 目标文本 | |
英文逗号(,) | 英文逗号(,) | 出现左侧一种或多中情况时,在文本两侧加上英文冒号(“ ) |
英文冒号(“ ) | 替换成两个英文冒号(“”) | |
换行符(\\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文件的主要内容,如果未能解决你的问题,请参考以下文章