如何拆分列可能包含的csv,
特定
2,1016,7 / 31/2008 14:22,Geoff Dalgas,2011年6月5日22:21,http://stackoverflow.com,“Corvallis,OR”,7679,351,81,b437f461b3fd27387c5d8ab47a293d35,34
如何使用C#将上面的信息分成string如下:
2 1016 7/31/2008 14:22 Geoff Dalgas 6/5/2011 22:21 http://stackoverflow.com Corvallis, OR 7679 351 81 b437f461b3fd27387c5d8ab47a293d35 34
正如你可以看到其中的一列包含<=(Corvallis,OR)
/ /更新/ /基于C#正则expression式拆分 – 逗号之外的引号
string[] result = Regex.Split(samplestring, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
使用Microsoft.VisualBasic.FileIO.TextFieldParser
类。 这将处理parsing分隔的文件, TextReader
或Stream
,其中一些字段用引号括起来,而另一些则不用。
例如:
using Microsoft.VisualBasic.FileIO; string csv = "2,1016,7/31/2008 14:22,Geoff Dalgas,6/5/2011 22:21,http://stackoverflow.com,\"Corvallis, OR\",7679,351,81,b437f461b3fd27387c5d8ab47a293d35,34"; TextFieldParser parser = new TextFieldParser(new StringReader(csv)); // You can also read from a file // TextFieldParser parser = new TextFieldParser("mycsvfile.csv"); parser.HasFieldsEnclosedInQuotes = true; parser.SetDelimiters(","); string[] fields; while (!parser.EndOfData) { fields = parser.ReadFields(); foreach (string field in fields) { Console.WriteLine(field); } } parser.Close();
这应该导致以下输出:
2 1016 7/31/2008 14:22 Geoff Dalgas 6/5/2011 22:21 http://stackoverflow.com 科瓦利斯,俄勒冈州 7679 351 81 b437f461b3fd27387c5d8ab47a293d35 34
有关更多信息,请参阅Microsoft.VisualBasic.FileIO.TextFieldParser 。
您需要在添加引用.NET选项卡中添加对Microsoft.VisualBasic
的引用。
你可以在所有的引号后面加上偶数的逗号。
你也想在CSV格式查看处理逗号。
有用的链接: C# Regex Split - commas outside quotes
我发现如果在Excel中粘贴csv分隔的文本并执行“文本到列”,它会要求您input“文本限定符”。 它被默认为双引号,因此它将双引号内的文本视为文字。 我想象一下,Excel通过一次只input一个字符来实现这个function,如果遇到“文本限定符”,它会继续执行下一个“限定符”。 你可以用for循环和boolean来实现这个,如果你是在文字里面的话。
public string[] CsvParser(string csvText) { List<string> tokens = new List<string>(); int last = -1; int current = 0; bool inText = false; while(current < csvText.Length) { switch(csvText[current]) { case '"': inText = !inText; break; case ',': if (!inText) { tokens.Add(csvText.Substring(last + 1, (current - last)).Trim(' ', ',')); last = current; } break; default: break; } current++; } if (last != csvText.Length - 1) { tokens.Add(csvText.Substring(last+1).Trim()); } return tokens.ToArray(); }
使用像LumenWorks这样的库来做你的CSV阅读。 它将处理带有引号的字段,并且由于已经存在了很长时间,所以可能总体上比您的定制解决scheme更加稳健。
.csv文件可以是逗号分隔的string,逗号分隔的引用string或两者的混淆组合时,parsing.csv文件是一个棘手的问题。 我提出的解决scheme允许三种可能性中的任何一种。
我创build了一个方法,ParseCsvRow()从csvstring返回一个数组。 我首先通过将双引号中的string拆分为一个名为quotesArray的数组来处理string中的双引号。 引用的string.csv文件只有在偶数个双引号的情况下才有效。 列值中的双引号应该用一对双引号replace(这是Excel的方法)。 只要.csv文件符合这些要求,您就可以期待分隔符逗号只出现在双引号对之外。 双引号内的逗号是列值的一部分,在将.csv分割成数组时应该忽略。
我的方法将通过仅查看引用数组的引号来testing双引号对之外的逗号。 它还从列值的开始和结束中删除双引号。
public static string[] ParseCsvRow(string csvrow) { const string obscureCharacter = "ᖳ"; if (csvrow.Contains(obscureCharacter)) throw new Exception("Error: csv row may not contain the " + obscureCharacter + " character"); var unicodeSeparatedString = ""; var quotesArray = csvrow.Split('"'); // Split string on double quote character if (quotesArray.Length > 1) { for (var i = 0; i < quotesArray.Length; i++) { // CSV must use double quotes to represent a quote inside a quoted cell // Quotes must be paired up // Test if a comma lays outside a pair of quotes. If so, replace the comma with an obscure unicode character if (Math.Round(Math.Round((decimal) i/2)*2) == i) { var s = quotesArray[i].Trim(); switch (s) { case ",": quotesArray[i] = obscureCharacter; // Change quoted comma seperated string to quoted "obscure character" seperated string break; } } // Build string and Replace quotes where quotes were expected. unicodeSeparatedString += (i > 0 ? "\"" : "") + quotesArray[i].Trim(); } } else { // String does not have any pairs of double quotes. It should be safe to just replace the commas with the obscure character unicodeSeparatedString = csvrow.Replace(",", obscureCharacter); } var csvRowArray = unicodeSeparatedString.Split(obscureCharacter[0]); for (var i = 0; i < csvRowArray.Length; i++) { var s = csvRowArray[i].Trim(); if (s.StartsWith("\"") && s.EndsWith("\"")) { csvRowArray[i] = s.Length > 2 ? s.Substring(1, s.Length - 2) : ""; // Remove start and end quotes. } } return csvRowArray; }
我的方法的一个缺点是我暂时用一个晦涩的unicode字符replace分隔符的方式。 这个angular色需要非常模糊,它不会出现在你的.csv文件中。 你可能想要更多的处理这个。
我遇到了一个包含带有引号字符的字段的CSV问题,所以使用TextFieldParser,我想出了以下内容:
private static string[] parseCSVLine(string csvLine) { using (TextFieldParser TFP = new TextFieldParser(new MemoryStream(Encoding.UTF8.GetBytes(csvLine)))) { TFP.HasFieldsEnclosedInQuotes = true; TFP.SetDelimiters(","); try { return TFP.ReadFields(); } catch (MalformedLineException) { StringBuilder m_sbLine = new StringBuilder(); for (int i = 0; i < TFP.ErrorLine.Length; i++) { if (i > 0 && TFP.ErrorLine[i]== '"' &&(TFP.ErrorLine[i + 1] != ',' && TFP.ErrorLine[i - 1] != ',')) m_sbLine.Append("\"\""); else m_sbLine.Append(TFP.ErrorLine[i]); } return parseCSVLine(m_sbLine.ToString()); } } }
StreamReader仍然用于逐行读取CSV,如下所示:
using(StreamReader SR = new StreamReader(FileName)) { while (SR.Peek() >-1) myStringArray = parseCSVLine(SR.ReadLine()); }