lyh916

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

参考链接:

https://www.cnblogs.com/lulianqi/p/6385503.html

http://blog.csdn.net/paul342/article/details/22800137

 

说明:

1.写入一个单元格时,如果含有逗号,则需要将整个字段用双引号括起来;如果里面还有双引号就替换成两个双引号。

2.写入一行时,末尾要加上\r\n作为行分隔符。

3.读取时,也要根据上面的写入规则进行解析。

 

代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.IO;
  4 using System.Text;
  5 
  6 public class CSVTool {
  7 
  8     private static char _csvSeparator = ',';
  9     private static bool _trimColumns = false;
 10 
 11     //获取一个单元格的写入格式
 12     public static string GetCSVFormat(string str)
 13     {
 14         string tempStr = str;
 15         if (str.Contains(","))
 16         {
 17             if (str.Contains("\""))
 18             {
 19                 tempStr = str.Replace("\"", "\"\"");
 20             }
 21             tempStr = "\"" + tempStr + "\"";
 22         }
 23         return tempStr;
 24     }
 25 
 26     //获取一行的写入格式
 27     public static string GetCSVFormatLine(List<string> strList)
 28     {
 29         string tempStr = "";
 30         for (int i = 0; i < strList.Count - 1; i++)
 31         {
 32             string str = strList[i];
 33             tempStr = tempStr + GetCSVFormat(str) + ",";
 34         }
 35         tempStr = tempStr + GetCSVFormat(strList[strList.Count - 1]) + "\r\n";
 36         return tempStr;
 37     }
 38 
 39     //解析一行
 40     public static List<string> ParseLine(string line)
 41     {
 42         StringBuilder _columnBuilder = new StringBuilder();
 43         List<string> Fields = new List<string>();
 44         bool inColumn = false;  //是否是在一个列元素里
 45         bool inQuotes = false;  //是否需要转义
 46         bool isNotEnd = false;  //读取完毕未结束转义
 47         _columnBuilder.Remove(0, _columnBuilder.Length);
 48 
 49         //空行也是一个空元素,一个逗号是2个空元素
 50         if (line == "")
 51         {
 52             Fields.Add("");
 53         }
 54 
 55         // Iterate through every character in the line
 56         for (int i = 0; i < line.Length; i++)
 57         {
 58             char character = line[i];
 59 
 60             // If we are not currently inside a column
 61             if (!inColumn)
 62             {
 63                 // If the current character is a double quote then the column value is contained within
 64                 // double quotes, otherwise append the next character
 65                 inColumn = true;
 66                 if (character == '"')
 67                 {
 68                     inQuotes = true;
 69                     continue;
 70                 }
 71 
 72             }
 73 
 74             // If we are in between double quotes
 75             if (inQuotes)
 76             {
 77                 if ((i + 1) == line.Length)//这个字符已经结束了整行
 78                 {
 79                     if (character == '"') //正常转义结束,且该行已经结束
 80                     {
 81                         inQuotes = false;
 82                         continue;     //当前字符不用添加,跳出后直结束后会添加该元素
 83                     }
 84                     else //异常结束,转义未收尾
 85                     {
 86                         isNotEnd = true;
 87                     }
 88                 }
 89                 else if (character == '"' && line[i + 1] == _csvSeparator) //结束转义,且后面有可能还有数据
 90                 {
 91                     inQuotes = false;
 92                     inColumn = false;
 93                     i++; //跳过下一个字符
 94                 }
 95                 else if (character == '"' && line[i + 1] == '"') //双引号转义
 96                 {
 97                     i++; //跳过下一个字符
 98                 }
 99                 else if (character == '"') //双引号单独出现(这种情况实际上已经是格式错误,为了兼容可暂时不处理)
100                 {
101                     throw new Exception("格式错误,错误的双引号转义");
102                 }
103                 //其他情况直接跳出,后面正常添加
104 
105             }
106             else if (character == _csvSeparator)
107                 inColumn = false;
108 
109             // If we are no longer in the column clear the builder and add the columns to the list
110             if (!inColumn) //结束该元素时inColumn置为false,并且不处理当前字符,直接进行Add
111             {
112                 Fields.Add(_trimColumns ? _columnBuilder.ToString().Trim() : _columnBuilder.ToString());
113                 _columnBuilder.Remove(0, _columnBuilder.Length);
114 
115             }
116             else // append the current column
117                 _columnBuilder.Append(character);
118         }
119 
120         // If we are still inside a column add a new one (标准格式一行结尾不需要逗号结尾,而上面for是遇到逗号才添加的,为了兼容最后还要添加一次)
121         if (inColumn)
122         {
123             if (isNotEnd)
124             {
125                 _columnBuilder.Append("\r\n");
126             }
127             Fields.Add(_trimColumns ? _columnBuilder.ToString().Trim() : _columnBuilder.ToString());
128         }
129         else  //如果inColumn为false,说明已经添加,因为最后一个字符为分隔符,所以后面要加上一个空元素
130         {
131             Fields.Add("");
132         }
133 
134 
135         return Fields;
136     }
137 
138     //读取文件
139     public static List<List<string>> Read(string filePath, Encoding encoding)
140     {
141         List<List<string>> result = new List<List<string>>();
142         string content = File.ReadAllText(filePath, encoding);
143         string[] lines = content.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
144         for (int i = 0; i < lines.Length; i++)
145         {
146             List<string> line = ParseLine(lines[i]);
147             result.Add(line);
148         }
149         return result;
150     }
151 
152     //写入文件
153     public static void Write(string filePath, Encoding encoding, List<List<string>> result)
154     {
155         StringBuilder builder = new StringBuilder();
156         for (int i = 0; i < result.Count; i++)
157         {
158             List<string> line = result[i];
159             builder.Append(GetCSVFormatLine(line));
160         }
161         File.WriteAllText(filePath, builder.ToString(), encoding);
162     }
163 
164     //打印
165     public static void Debug(List<List<string>> result)
166     {
167         for (int i = 0; i < result.Count; i++)
168         {
169             List<string> line = result[i];
170             for (int j = 0; j < line.Count; j++)
171             {
172                 UnityEngine.Debug.LogWarning(line[j]);
173             }
174         }
175     }
176 }

 

测试:

posted on 2018-03-17 10:53  艰苦奋斗中  阅读(1372)  评论(0编辑  收藏  举报