如何使用C#处理CSV文件中的换行符?
我有一个Excel电子表格在C#中转换为CSV文件,但在处理换行符时遇到问题。 例如:
"John","23","555-5555" "Peter","24","555-5 555" "Mary,"21","555-5555"
当我读取CSV文件时,如果记录没有以双引号(“)开头,那么就会出现换行错误,我必须将其删除。我有一些来自互联网的CSV读取器类但我担心它们在换行时会失败。
我该如何处理这些换行符?
非常感谢大家的帮助。
heres是我到目前为止所做的,我的记录有固定的格式,一切都从一开始
JTW;...;....;...; JTW;...;...;.... JTW;....;...;.. ..;...;... (wrong record, line brak inserted) JTW;...;...
所以我检查了;
在每行的[3]位置。 如果我写的是真的,如果假病附加在最后*删除换行符)
我现在遇到问题,因为我将文件保存为txt。
顺便说一句,我通过在excell中保存为csv将excell spreadshit转换为csv。 但我不确定客户是否这样做。
所以作为TXT的文件是完美的。 香港专业教育学院检查了记录和总数。 但现在我必须将它转换回csv,我真的很想在程序中做到这一点。 有人知道吗?
这是我的代码:
namespace EditorCSV { class Program { static void Main(string[] args) { ReadFromFile("c:\\source.csv"); } static void ReadFromFile(string filename) { StreamReader SR; StreamWriter SW; SW = File.CreateText("c:\\target.csv"); string S; char C='a'; int i=0; SR=File.OpenText(filename); S=SR.ReadLine(); SW.Write(S); S = SR.ReadLine(); while(S!=null) { try { C = S[3]; } catch (IndexOutOfRangeException exception){ bool t = false; while (t == false) { t = true; S = SR.ReadLine(); try { C = S[3]; } catch (IndexOutOfRangeException ex) { S = SR.ReadLine(); t = false; } } } if( C.Equals(';')) { SW.Write("\r\n" + S); i = i + 1; } else { SW.Write(S); } S=SR.ReadLine(); } SR.Close(); SW.Close(); Console.WriteLine("Records Processed: " + i.ToString() + " ."); Console.WriteLine("File Created SucacessFully"); Console.ReadKey(); } } }
CSV具有预定义的处理方式。 该站点提供了一个易于阅读的解释,说明了处理CSV的所有警告的标准方法 。
然而,没有理由不使用可靠的开源库来读取和写入CSV文件,以避免出现非标准错误。 LINQtoCSV是我最喜欢的库。 它以简洁的方式支持阅读和书写。
或者, CSV库上的这个SO问题将为您提供最受欢迎的选项列表。
而不是检查当前行是否缺少(“)作为第一个字符,而是检查最后一个字符是否为(”)。 如果不是,您知道您有换行符,您可以阅读下一行并将它们合并在一起。
我假设您的示例数据是准确的 – 字段用引号括起来。 如果引号可能不会分隔文本字段(或者在非文本数据中以某种方式找到新行),则所有投注都会关闭!
有一种在.NET中读取CSV文件的内置方法(需要添加Microsoft.VisualBasic程序集引用):
public static IEnumerable ReadSV(TextReader reader, params string[] separators) { var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(reader); parser.SetDelimiters(separators); while (!parser.EndOfData) yield return parser.ReadFields(); }
如果你正在处理非常大的文件,这个CSV阅读器声称是你能找到的最快的文件: http : //www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
我最近使用这段代码来解析CSV文件中的行(这是一个简化版本):
private void Parse(TextReader reader) { var row = new List(); var isStringBlock = false; var sb = new StringBuilder(); long charIndex = 0; int currentLineCount = 0; while (reader.Peek() != -1) { charIndex++; char c = (char)reader.Read(); if (c == '"') isStringBlock = !isStringBlock; if (c == separator && !isStringBlock) //end of word { row.Add(sb.ToString().Trim()); //add word sb.Length = 0; } else if (c == '\n' && !isStringBlock) //end of line { row.Add(sb.ToString().Trim()); //add last word in line sb.Length = 0; //DO SOMETHING WITH row HERE! currentLineCount++; row = new List (); } else { if (c != '"' && c != '\r') sb.Append(c == '\n' ? ' ' : c); } } row.Add(sb.ToString().Trim()); //add last word //DO SOMETHING WITH LAST row HERE! }
也许你可以在ReadLine()期间计算(“)。如果它们是奇数,那将提升标志。你可以忽略这些行,或者获得接下来的两行并消除合并行的第一次”\ n“出现。
由于这个问题,我通常做的是逐行逐字逐字地阅读文本。
当你正在阅读每个角色时,你应该能够找出每个单元格的开始和停止位置,以及行和单元格中的换行符之间的区别:如果我没记错的话,对于Excel生成的文件无论如何,行开始使用\ r \ n,单元格中的换行符仅为\ r \ n。
听从专家的意见, 不要推出自己的CSV解析器 。
你的第一个想法是,“我如何处理新的换行符?”
你的下一个想法是,“我需要在引号内处理逗号。”
你的下一个想法是,“哦,废话,我需要处理引号内的引号。转义引号。双引号。单引号……”
这是一条通向疯狂的道路。 不要自己写。 找到一个具有广泛的unit testing覆盖率的图书馆,该图书馆覆盖了所有的硬件,并为您经历了地狱。 对于.NET,请使用免费的FileHelpers库 。
试试CsvHelper (我维护的库)。 它忽略了空行。 我相信你可以在FastCsvReader中设置一个标志来让它处理空行。
有一个示例解析器是c#,似乎正确处理您的情况。 然后,您可以读取您的数据并在读取后清除它的换行符。 第2部分是解析器, 第1部分介绍了编写器部分。
阅读该行。
分成列(字段)。
如果每行都有足够的列,则进行处理。
如果没有,请阅读下一行,并捕获剩余的列,直到获得所需的内容。
重复。
可以在每一行上使用一个简单的正则表达式。 匹配时,您将处理匹配中的每个字段。 如果找不到匹配项,则跳过该行。
正则表达式看起来像这样。
Match match = Regex.Match(line, @"^(?:,?(?['"](?.*?\k'q')|(? [^,]*))+$"); if (match.Success) { foreach (var capture in match.Groups["field"].Captures) { string fieldValue = capture.Value; // Use the value. } }
看一下FileHelpers Library它支持使用换行符读取\写入CSV以及读取\写入excel
LINQy解决方案:
string csvText = File.ReadAllText("C:\\Test.txt"); var query = csvText .Replace(Environment.NewLine, string.Empty) .Replace("\"\"", "\",\"").Split(',') .Select((i, n) => new { i, n }).GroupBy(a => an / 3);