CSV⽂件对逗号和引号字符的转义处理,使⽤EXCEL打开时
在⼀个单元格内
CSV⽂件本质是⼀种⽤逗号和(回车)换⾏符分割的⽂本⽂件,可以直接⽤Excel打开
* CSV (逗号分隔值⽂件格式)Comma-Separated Values 【每⼀⾏的分割符必须是英⽂的逗号,不能是中⽂的逗号】
* 逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其⽂件以纯⽂本形式存储表格数据(数字和⽂本)。
* 纯⽂本意味着该⽂件是⼀个字符序列,不含必须像⼆进制数字那样被解读的数据。
* CSV⽂件由任意数⽬的记录组成,记录间以某种换⾏符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。
param name* 通常,所有记录都有完全相同的字段序列。通常都是纯⽂本⽂件.
* 建议使⽤WORDPAD或是记事本来开启,再则先另存新档后⽤EXCEL开启,也是⽅法之⼀。
*
* CSV格式是分隔的数据格式,有字段/列分隔的逗号字符和记录/⾏分隔换⾏符。
* 字段包含特殊字符(逗号,换⾏符,或双引号),必须以双引号括住。⾏内包含⼀个项⽬是空字符串,可以以双引号括住。
* 字段的值包含双引号时,要双写这个双引号(就像把⼀个双引号当做转义符⼀样)。
* CSV⽂件格式并不需要特定的字符编码,字节顺序,或⾏终⽌格式。
* 每个记录是⼀个⾏终⽌换⾏符(ASCII码/LF = 0x0A) 或 回车换⾏符(ASCII码/CRLF = 0x0D0A)。
* 0x0A【换⾏符】 在C#中代表字符 '\n'
* 0x0D0A【回车换⾏】 在C#中代表字符串 "\r\n"
*
* 转义(Escaped)要求:
* 包含逗号, 双引号, 或是换⾏符的字段必须放在引号内.【使⽤引号来进⾏特殊符号 Escaped转义】
* 字段内部的引号必须在其前⾯增加⼀个引号来实现⽂字引号的转码.
*
* 规则:
* 1 开头是不留空,以⾏为单位。
* 2 可含或不含列名,含列名则居⽂件第⼀⾏。
* 3 ⼀⾏数据不跨⾏,⽆空⾏。
* 4 以半⾓英⽂逗号(即,)作分隔符,列为空也要表达其存在。
* 5 列内容如存在半⾓引号(即"),替换成半⾓双引号("")转义,即⽤半⾓引号(即"")将该字段值包含起来。
* 6 ⽂件读写时引号,逗号操作规则互逆。
* 7 内码格式不限,可为 ASCII、Unicode 或者其他。
* 8 不⽀持数字
* 9 不⽀持特殊字符
我们使⽤时,如果不对引号 或者 逗号 进⾏特殊处理,使⽤Excel打开就会排列不美观,如图:
如果进⾏转义(Escaped)处理,如图:
对CSV⽂件的每⼀项都进⾏转义处理,关键函数如下:
/// <summary>
/// 处理csv⽂件中的双引号和逗号,使其在Excel中完美显⽰为⼀个单元格
/
// 斯内科 20210321
/// </summary>
/// <param name="srcStr"></param>
/// <returns></returns>
private static string ProcessPunctuationForCsv(string srcStr)
{
if (srcStr == null)
{
return string.Empty;
}
bool quoteFlag = false;//是否添加过双引号
/
/如果存在双引号,需要将字符串的⼀个双引号替换为两个双引号。并且需要在字符串的前后加上双引号            if (srcStr.Contains("\""))
{
srcStr = srcStr.Replace("\"", "\"\"");
srcStr = "\"" + srcStr + "\"";
quoteFlag = true;
}
//如果只存在逗号(不存在引号),将前后加引号即可
if (srcStr.Contains(",") && !quoteFlag)
{
srcStr = "\"" + srcStr + "\"";
}
return srcStr;
}
下⾯使⽤Winform程序进⾏验证:
新建窗体应⽤程序CsvFileEscapedDemo,将默认的Form1重命名为 FormCsvFileEscaped
窗体设计如图:
新建测试类Employee.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CsvFileEscapedDemo
{
/// <summary>
/// 员⼯信息
/// </summary>
public class Employee
{
public Employee()
{
this.ListSkills = new List<string>();
}
/// <summary>
/// 编号
/// </summary>
public int CoreId { get; set; }
/// <summary>
/
// 姓名
/// </summary>
public string EmployeeName { get; set; }
/// <summary>
/// 地址
/// </summary>
public string Address { get; set; }
/// <summary>
/// 技能列表
/// </summary>
public List<string> ListSkills { get; set; }
}
}
新建读写CSV的相关类CsvUtil 相关程序如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CsvFileEscapedDemo
{
/// <summary>
/// 对CSV⽂件进⾏读写
/// </summary>
public class CsvUtil
{
/*
* 1:csv与Excel本质区别是⽂本⽂件
* 2:每个单元格的数据⽤,分割
* 2:每个单元格的数据⽤,分割
* 3:每⾏的数据⽤\r\n分割
*/
private static Object thisLock = new Object();
/// <summary>
/// 创建Csv
/// </summary>
/// <param name="_path">路径</param>
/// <param name="_name">名称</param>
/// <returns></returns>
public static bool CreateCsv(string _path, string _name)
{
lock (thisLock)
{
try
{
using (File.Create(_path + _name + ".csv"))
{
}
return true;
}
catch (Exception)
{
return false;
}
}
}
/// <summary>
/// 删除Csv
/// </summary>
/// <param name="_path">路径</param>
/// <param name="_name">名称</param>
/// <returns></returns>
public static bool DeleteCsv(string _path, string _name)
{
string _tmPath = _path + _name + ".csv";
lock (thisLock)
{
try
{
if (File.Exists(_tmPath) == true)
{
File.Delete(_tmPath);
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
MessageBox.Show("CSV⽂件删除失败:" + e.Message);                    return false;
}
}
}
/// <summary>
/
// 读取csv
/// </summary>
/// <param name="_path">路径,如 @"D:\MESLog\ABC\"</param>
/// <param name="_path">路径,如 @"D:\MESLog\ABC\"</param>
/// <param name="_name">名称,不带.csv</param>
/// <param name="_recvData">读取到的数据</param>
/// <returns></returns>
public static bool ReadCsv(string _path, string _name, ref List<string[]> _recvData)
{
return ReadCsv(Path.Combine(_path, _name + ".csv"), ref _recvData);
}
/
// <summary>
/// 读取csv
/// </summary>
/// <param name="_path">路径,如 @"D:\MESLog\ABC\"</param>
/// <param name="_name">名称,不带.csv</param>
/// <param name="_recvData">读取到的数据</param>
/// <param name="errorMsg">异常信息</param>
/// <returns></returns>
public static bool ReadCsv(string _path, string _name, ref List<string[]> _recvData, ref string errorMsg)        {
return ReadCsv(Path.Combine(_path, _name + ".csv"), ref _recvData, ref errorMsg);
}
/// <summary>
/// 读取csv⽂件
/// </summary>
/// <param name="_fullfilePath">全路径</param>
/// <param name="recvData">返回的值</param>
/// <returns></returns>
public static bool ReadCsv(string fullfilePath, ref List<string[]> recvData)
{
string errorMsg = "";
return ReadCsv(fullfilePath, ref recvData, ref errorMsg);
}
/
// <summary>
/// 读取csv⽂件
/// </summary>
/// <param name="_fullfilePath">全路径</param>
/// <param name="recvData">返回的值</param>
/// <returns></returns>
public static bool ReadCsv(string fullfilePath, ref List<string[]> recvData, ref string errorMsg)
{
lock (thisLock)
{
try
{
if (!fullfilePath.Contains(".csv"))
{
errorMsg = "路径中没有.csv后缀";
return false;
}
string _tmPath = fullfilePath;
using (StreamReader reader = new StreamReader(_tmPath, Encoding.Default))
{
string _lin = reader.ReadToEnd().Trim();
string[] _str = _lin.Split('\n');
recvData.Clear();
for (int i = 0; i < _str.Length; i++)
{
_str[i] = _str[i].TrimEnd('\r');
recvData.Add(_str[i].Split(','));
}
}
return true;
}
catch (Exception e)
{
errorMsg = e.Message;
MessageBox.Show("CSV⽂件读取失败:" + e.Message);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。