CSV全称是Comma-Separated Values(逗号分隔值)。作为一种数据传输与存储的格式,它显然没有xml,json强大,只能进行一些二维数组的数据处理,但它在项目还是经常会用到.

CSV的字符规则:

1 开头是不留空,以行为单位。

2 可含或不含列名,含列名则居文件第一行。

3 一行数据不跨行,无空行。

4 以半角逗号(即,)作分隔符,列为空也要表达其存在。

5 列内容如存在半角逗号(即,)换行符\r(10)\n(13)则用半角引号(即"")将该字段值包含起来。

6 列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。

7 文件读写时引号,逗号操作规则互逆。

8 内码格式不限,可为 ASCII、Unicode 或者其他。

9 数据结束外,有\r\n作为结束标记

说明:这个规则对于excel完全适合

算法实现

namespace CSV
{
/// <summary>
/// CSVUtil 用来处理CSV格式的文件内容成一二维数组。
/// </summary>
public class CSVUtil
{
private string content;
public CSVUtil()
{ }
public CSVUtil(string _content)
{
content = _content;
}
public CSVUtil(string _content, bool _hasHeader)
{
content = _content;
hasHeader = _hasHeader;
} private bool hasHeader = true;
public bool HasHeader
{
get { return hasHeader; }
set { hasHeader = value; }
} private string[] headr;
public string[] Header
{
get { return headr; }
} private string[][] data;
public string[][] Data
{
get { return data; }
} /// <summary> /// 分割 CVS 文件内容为一个二维数组。 /// </summary> /// <param name="src">CVS 文件内容字符串</param> /// <returns>二维数组。String[line count][column count]</returns> public void Parse()
{ // 如果输入为空,返回 0 长度字符串数组 if (content == null || content.Length == 0) return;
string st = "";
List<List<string>> lines = new List<List<string>>(); // 行集合。其元素为行
List<string> cells = new List<string>(); // 单元格集合。其元素为一个单元格
bool beginWithQuote = false;
int maxColumns = 0;
// 遍历字符串的字符
for (int i = 0; i < content.Length; i++)
{
char ch = content[i];
#region CR 或者 LF
//A record separator may consist of a line feed (ASCII/LF=0x0A),
//or a carriage return and line feed pair (ASCII/CRLF=0x0D 0x0A).
// 这里我不明白CR为什么不作为separator呢,在Mac OS上好像是用CR的吧。
// 这里我“容错”一下,CRLF、LFCR、CR、LF都作为separator if (ch == '\r')
{
#region CR
if (beginWithQuote)
{
st += ch;
}
else
{
if (i + 1 < content.Length && content[i + 1] == '\n')
{ // 如果紧接的是LF,那么直接把LF吃掉
i++;
} //line = new String[cells.Count];
//System.Array.Copy (cells.ToArray(typeof(String)), line, line.Length);
//lines.Add(line); // 把上一行放到行集合中去 cells.Add(st);
st = "";
beginWithQuote = false;
maxColumns = (cells.Count > maxColumns ? cells.Count : maxColumns);
lines.Add(cells);
st = "";
cells = new List<string>();
}
#endregion CR
} else if (ch == '\n')
{
#region LF
if (beginWithQuote)
{
st += ch;
}
else
{
if (i + 1 < content.Length && content[i + 1] == '\r')
{ // 如果紧接的是LF,那么直接把LF吃掉
i++;
}
//line = new String[cells.Count];
//System.Array.Copy (cells.ToArray(typeof(String)), line, line.Length);
//lines.Add(line); // 把上一行放到行集合中去 cells.Add(st);
st = "";
beginWithQuote = false;
maxColumns = (cells.Count > maxColumns ? cells.Count : maxColumns);
lines.Add(cells);
st = "";
cells = new List<string>(); }
#endregion LF
} #endregion CR 或者 LF
else if (ch == '\"')
{ // 双引号
#region 双引号 if (beginWithQuote)
{
i++;
if (i >= content.Length)
{
cells.Add(st);
st = "";
beginWithQuote = false;
}
else
{
ch = content[i];
if (ch == '\"')
{
st += ch;
}
else if (ch == ',')
{
cells.Add(st);
st = "";
beginWithQuote = false;
}
else
{
throw new Exception("Single double-quote char mustnt exist in filed " + (cells.Count + 1) + " while it is begined with quote\nchar at:" + i);
}
}
} else if (st.Length == 0)
{
beginWithQuote = true;
} else
{
throw new Exception("Quote cannot exist in a filed which doesnt begin with quote!\nfield:" + (cells.Count + 1));
}
#endregion 双引号
} else if (ch == ',')
{
#region 逗号
if (beginWithQuote)
{
st += ch;
}
else
{
cells.Add(st);
st = "";
beginWithQuote = false;
}
#endregion 逗号
} else
{
#region 其它字符
st += ch;
#endregion 其它字符
} } if (st.Length != 0)
{
if (beginWithQuote)
{
throw new Exception("last field is begin with but not end with double quote");
}
else
{
cells.Add(st);
maxColumns = (cells.Count > maxColumns ? cells.Count : maxColumns);
lines.Add(cells);
}
}
int dataRowCount = hasHeader ? lines.Count - 1 : lines.Count;
data = new string[dataRowCount][];
for (int i = 0; i < lines.Count; i++)
{
cells = (List<string>)lines[i];
try
{
if (hasHeader == true && i == 0)
{
headr = new string[maxColumns];
for (int j = 0; j < maxColumns; j++)
{
headr[j] = cells[j];
}
}
else
{
int dataIndex = hasHeader ? i - 1 : i;
data[dataIndex] = new string[maxColumns];
for (int j = 0; j < maxColumns; j++)
{
data[dataIndex][j] = cells[j];
}
}
}
catch (Exception ex)
{ throw new Exception(ex.Message + "\nfield:" + (i + 1));
}
}
//System.Array.Copy(lines.ToArray(typeof(String[])), ret, ret.Length);
return; } public static string FormatField(object obj)
{
string result = string.Empty;
if (obj != null)
{
string old = obj.ToString(); if (old.IndexOf('\"') > -1 || old.IndexOf(',') > -1 || old.IndexOf('\n') > -1 || old.IndexOf('\r') > -1)
{
result = "\"" + old.Replace("\"", "\"\"") + "\"";
}
else
{
result = old;
}
}
return result;
} public static string FormatList<T>(IEnumerable<T> source, List<string> outputPropertys)
{
StringBuilder sbResult = new StringBuilder();
Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();
object val = null;
foreach (string propertyName in outputPropertys)
{
PropertyInfo p = typeof(T).GetProperty(propertyName);
methods.Add(propertyName, p.GetGetMethod());
sbResult.Append(propertyName + ",");
}
sbResult.Remove(sbResult.Length - 1, 1);
sbResult.Append(Environment.NewLine);
foreach (T item in source)
{
foreach (KeyValuePair<string, MethodInfo> method in methods)
{
val = method.Value.Invoke(item, null);
sbResult.Append(FormatField(val) + ",");
}
sbResult.Remove(sbResult.Length - 1, 1);
sbResult.Append(Environment.NewLine);
}
return sbResult.ToString();
}
}
}

细说CSV的更多相关文章

  1. csvkit---python一个牛逼到不行的csv处理库

    先吐槽一下:不管是百度还是谷歌,查来查去除了官方文档之外就没有任何可以借鉴的例子,虽然官方文档写的挺好的.但是我一直以为是在python语言的方式运行的,结果是以命令行的方式运行的,搞得我还以为这个库 ...

  2. PHP生成器细说

    之前写过关于生成器的文章,可能还不够详细,正好群里有朋友在讨论.觉得还是有必要再细说下,如果大家做过Python或者其他语言的,对于生成器应该不陌生.生成器是PHP 5.5.才引入的功能,也许大家觉得 ...

  3. [转]RPA认证 Developer UIPath Certificate,细说uipath认证学习,Online Quiz和Practical Exam项目详解

    本文转自:https://blog.csdn.net/u010369735/article/details/88621195 UIPath,RPA里算是比较简单易操作的一款软件了,因为公司业务的需要, ...

  4. 匹夫细说C#:庖丁解牛迭代器,那些藏在幕后的秘密

    0x00 前言 在匹夫的上一篇文章<匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置>的最后,匹夫以总结和后记的方式涉及到一部分迭代器的知识.但是觉得还是不够过瘾,很多需要说清楚 ...

  5. 细说WebSocket - Node篇

    在上一篇提高到了 web 通信的各种方式,包括 轮询.长连接 以及各种 HTML5 中提到的手段.本文将详细描述 WebSocket协议 在 web通讯 中的实现. 一.WebSocket 协议 1. ...

  6. mysql 大表拆分成csv导出

    最近公司有一个几千万行的大表需要按照城市的id字段拆分成不同的csv文件. 写了一个自动化的shell脚本 在/home/hdh 下面 linux-xud0:/home/hdh # lltotal 1 ...

  7. Bulk Insert:将文本数据(csv和txt)导入到数据库中

    将文本数据导入到数据库中的方法有很多,将文本格式(csv和txt)导入到SQL Server中,bulk insert是最简单的实现方法 1,bulk insert命令,经过简化如下 BULK INS ...

  8. 匹夫细说C#:委托的简化语法,聊聊匿名方法和闭包

    0x00 前言 通过上一篇博客<匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的>的内容,我们实现了使用委托来构建我们自己的消息系统的过程.但是在日常的开发中,仍然有很多开发者因为 ...

  9. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

随机推荐

  1. mysql 彻底解决:Incorrect string value: '\xF0\x9F\x98\xAD",...' for column 'commentContent' at row 1

    彻底解决:Incorrect string value: '\xF0\x9F\x98\xAD",...' for column 'commentContent' at row 1 今天在爬取 ...

  2. 006 Android XML 文件布局及组件属性设置技巧汇总

    1.textview 组件文本实现替换(快速实现字符资源的调用) android 应用资源位置在 project(工程名)--->app--->res--->values 在stri ...

  3. ASP.NET 设计模式分为三种类型

    设计模式分为三种类型,共23类.  一.创建型模式:单例模式.抽象工厂模式.建造者模式.工厂模式.原型模式.      二.结构型模式:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代 ...

  4. POJ2248 Addition Chains 迭代加深

    不知蓝书的标程在说什么,,,,于是自己想了一下...发现自己的代码短的一批... 限制搜索深度+枚举时从大往小枚举,以更接近n+bool判重,避免重复搜索 #include<cstdio> ...

  5. LeetCode934.shortest bridge【dfs+bfs】

    一.题面 在给定的二维二进制数组 A 中,存在两座岛.(岛是由四面相连的 1 形成的一个最大组.) 现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛. 返回必须翻转的 0 的最小数目.( ...

  6. QDU_组队训练(AJFC)

    A - Pretty Matrix DreamGrid's birthday is coming. As his best friend, BaoBao is going to prepare a g ...

  7. bzoj1818 内部白点(好题) 离散化+树状数组

    题目传送门 题意:给出很多黑点,当一个坐标上下左右都有黑点时,这个点也被染成黑色,问最后黑点的数量. 思路:首先,一个很显然的结论,不可能出现无限染色的情况.所以不会输出-1,当n为0或者1时,答案就 ...

  8. HDU 5938 Kingdom of Obsession(数论 + 二分图匹配)

    题意: 给定S,N,把S+1,S+2,...S+N这N个数填到1,2,...,N里,要求X只能填到X的因子的位置.(即X%Y=0,那么X才能放在Y位置) 问是否能够放满. 分析:经过小队的分析得出的结 ...

  9. POJ - 3735 循环操作

    构造n+1元组,m次方的矩阵代表循环操作 本题尚有质疑之处(清零操作的正确性还有单位矩阵的必要性),题解可能会改正 #include<iostream> #include<algor ...

  10. Spring Boot 例一 实现jsonp接口

    1.新建项目(选择quikstart) 2.增加spring boot 依赖 <dependency> <groupId>org.springframework.boot< ...