参考链接:
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 }
测试: