兼容标准的CSV文件读写类
这几天工作要读写CSV文件,CSV格式虽然很简单,为省事想先从网上找一个现成的,但找了半天只有一个看上去可以,至少读写都支持,在此基础上,按照标准修正了一下,标准才是王道。
贴一下CSV格式标准规则,来自百度百科 http://baike.baidu.com/view/468993.htm:
1 开头是不留空,以行为单位。
2 可含或不含列名,含列名则居文件第一行。
3 一行数据不垮行,无空行。
4 以半角逗号(即,)作分隔符,列为空也要表达其存在。
5 列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。
6 列内容如存在半角引号(即")则应替换成半角双引号("")转义。
7 文件读写时引号,逗号操作规则互逆。
8 内码格式不限,可为ASCII、Unicode或者其他。
9 不支持特殊字符和中文。
网上看到的,都满足前4条,5和6基本都没考虑,应该只是为处理自己手头工作需要而用。其实只继续努力一下,让它变成通用的,再共享出来就有价值的多。
此类可以读文件或流的数据,返回DataTable。也可以将DataTable处理后保存成csv文件。
public class CsvHelper{public CsvHelper() { }public CsvHelper(string csvFile){this.CsvFile = csvFile;}public string CsvFile { get; set; }public DataTable Read(Stream stream){if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin);return Read(new StreamReader(stream));}public DataTable Read(){if (String.IsNullOrEmpty(CsvFile)) throw new InvalidOperationException("File name can't be null or empty.");StreamReader reader = new StreamReader(this.CsvFile);return Read(reader);}private DataTable Read(TextReader reader){string line = string.Empty;int lineNumber = 0;DataTable dt = null;try{while ((line = reader.ReadLine()) != null){if (lineNumber == 0){//Create Toledt = CreateDataTable(line);if (dt.Columns.Count == 0) return null;}else{bool added = CreateDataRow(dt, line);if (!added) break; //Meet the empty rows.}lineNumber++;}}finally{reader.Close();}return dt;}public void Write(DataTable dt){if (String.IsNullOrEmpty(CsvFile)) throw new InvalidOperationException("File name can't be null or empty.");Write(dt, this.CsvFile);}public void Write(DataTable dt, string filename){var sb = WriteString(dt);using (StreamWriter writer = new StreamWriter(filename)){writer.Write(sb);writer.Flush();}}public string WriteString(DataTable dt){if (dt == null) throw new ArgumentNullException("dt");var sb = new System.Text.StringBuilder(9999);for (int i = 0; i < dt.Columns.Count; i++){if (i > 0) sb.Append(',');sb.Append(dt.Columns[i].ColumnName);}sb.Append(Environment.NewLine);foreach (DataRow dr in dt.Rows){for (int i = 0; i < dt.Columns.Count; i++){var text = dr[i] as string;if (text.IndexOf('"') >= 0) text = text.Replace("\"", "\"\""); //Replace quote to double quotes.if (text.IndexOf(',') >= 0) text = '"' + text + '"';if (i > 0) sb.Append(',');sb.Append(text);}sb.Append(Environment.NewLine);}return sb.ToString();}/// <summary>/// Init DataTable's colomns/// </summary>/// <param name="line"></param>/// <returns></returns>private DataTable CreateDataTable(string line){DataTable dt = new DataTable();foreach (string field in line.Split(',')){dt.Columns.Add(field);}return dt;}private bool CreateDataRow(DataTable dt, string line){DataRow dr = dt.NewRow();string[] fields = new string[dt.Columns.Count];bool add = true;int index = 0;for (int i = 0; i < dt.Columns.Count; i++){if (index >= line.Length) break;var text = ReadField(ref index, line);if (i == 0 && text.Length == 0){add = false;break;}dr[i] = text;}if (add) dt.Rows.Add(dr);return add;}private string ReadField(ref int startIndex, string line){int endIndex;string text;if (line[startIndex] == '"'){startIndex++;endIndex = line.IndexOf("\",", startIndex); //The normal case, except the end of line.if (endIndex == -1){endIndex = line.IndexOf(',', startIndex); //Unnormal case, a comma required.if (endIndex == -1) endIndex = line.Length; //Meet string's end.if (line[endIndex - 1] == '"') endIndex--; //The normal case.}text = line.Substring(startIndex, endIndex - startIndex);startIndex = endIndex + 2;}else{endIndex = line.IndexOf(',', startIndex);if (endIndex == -1) endIndex = line.Length; //Meet string's end.text = line.Substring(startIndex, endIndex - startIndex);startIndex = endIndex + 1;}if (text.Contains("\"\"")) text = text.Replace("\"\"", "\"");return text;}}
处理边界条件,如行尾时,要特别小心。既要保证功能正确,又要确保一定的健壮性和容错性。
这是个不依赖状态的类,也就是其中大部分方法都可以转换为静态方法,看你心情了。希望下次有人像我一样偷懒时,能幸运地google到这篇。
兼容标准的CSV文件读写类相关推荐
- [Python从零到壹] 三.语法基础之文件操作、CSV文件读写及面向对象
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- python2.7读取csv文件_13.1. csv — CSV 文件读写 — Python 2.7.18 文档
13.1.csv - CSV 文件读写¶ 2.3 新版功能. The so-called CSV (Comma Separated Values) format is the most common ...
- c++怎么可以在二进制文件中读取带string的数据_文件处理 | csv文件读写
欢迎关注公众号 学习资料不会少 文件处理 在我们做自动化测试的过程中,常常会将数据文件存放在csv或者Excel文件里边.这一章节内容将给大家介绍,如何使用python进行csv和Excel文件的处理 ...
- python 写csv加锁_Python: 对CSV文件读写 和 Md5加密
1. python 有专门的csv包,直接导入即可. import csv: 2. 直接使用普通文件的open方法 csv_reader=open("e:/python/csv_data/l ...
- Tensorflow csv文件读写与分批训练
Tensorflow-1: csv文件读写与分批训练 原创 2017年04月29日 22:28:23 1509 今天尝试了一下读写csv文件并使用tensorflow训练数据,很方便. 程序训练的一个 ...
- VC中海量文件读写类设计与应用(转)
VC中海量文件读写类设计与应用 沈瑞冰 摘要 本文阐述了海量文件读写的一般方法,并分析了该方法中存在的内存耗尽问题和解决办法,并就此设计了一个海量文件读写类,封装了海量文件读写操作,最后给出了一个 ...
- C#常用类库----CSV文件操作类
using System.Data; using System.IO;namespace DotNet.Utilities {/// <summary>/// CSV文件转换类/// &l ...
- VC中海量文件读写类设计与应用
VC中海量文件读写类设计与应用 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile ...
- day08学习 Python文件函数、CSV文件读写
文件函数 seek seek(参数1,参数2) - 能够将指针移动指定的偏移量 参数1:移动的偏移量,默认为0 参数2: 0 - 将指针移动到文件开头 1 - (默认)- 指针指向当前位置 2 ...
- 标准库:csv --- CSV 文件读写
CSV (Comma Separated Values) 格式是电子表格和数据库中最常见的输入.输出文件格式. csv 模块实现了 CSV 格式表单数据的读写.其提供了诸如"以兼容 Exce ...
最新文章
- Springboot使用Maven Profile和Spring Profile进行多环境配置
- spring整合mybatis(入门级简单教程4)--扫描mapper类
- 世界隐形冠军比拼:德国1307家、美国366家、中国68家
- Python基础-re模块
- 鸿蒙so系统,鸿蒙手机版JNI实战(JNI开发、SO库生成、SO库使用)
- 你买过假芯片吗?元器件专家为您揭秘假冒芯片的套路!
- PHP3.2.3 where or,WHERE · ThinkPHP3.2.3完全开发手册 · 看云
- 遍历文件夹下所有文件,编辑删除
- 8266不通过usb供电_HomePod mini?电源线同样不可拆卸:但或能用USB-C移动电源供电...
- Prim和Kruskal算法
- Java21天打卡day19-异常
- 手把手教你强化学习 (七) 强化学习中的无模型控制
- 9.Jenkins 权威指南 --- Jenkins 维护
- HTML 管理员登陆小功能 连接数据库
- 《孤独的美食家》60家餐厅超全觅食攻略,吃货必收!
- BGP多线和双线双IP服务器有什么区别? 哪个网站访问速度更快?
- 进入显示器工厂模式的方法! 【95种品牌,维修珍藏资料】
- SEM纳米颗粒图像粒径分析 基于ImageJ
- 7-108 奇数偶数-zzuli
- 专访架构师周爱民:谈企业软件架构设计 1
热门文章
- jQuery1.3以上版本@的问题
- 顶点计划:辅导员与学生关系讨论
- An internal error occurred during: Launching web on MyEclipse Tomcat
- Asp.net-MyFirstMVCProject详细解释
- 奇怪,为什么在主页上面只列出最近的随笔,而文章呢?
- qkerntool使用说明
- 利用ComplexHeatmap绘制热图(一)
- lisp把多段线顶点连成表_读取多段线顶点并将顶点坐标标到数组中
- coredump详解
- Egret入门学习日记 --- 第九篇(书中 2.7~2.8节 内容)