C# 分析数据中带有逗号的CSV
可能重复:C# 分析数据中带有逗号的CSV,c#,.net,csv,C#,.net,Csv,可能重复: 我为自己编写了一个CSV解析器,它工作正常,直到我达到以下记录: B002VECGTG,B002VECGTG,拥有17131个空间射手,“4426”,0.04%,4832%,0.03%,0%,1,0.02%,20.47美元,1 在“4426”和“4426”中,转义的命令阻止了我的解析器 这是我用来解析文本行的内容: char[] comma = { ',' }; string[] words = line.Split(comma);
我为自己编写了一个CSV解析器,它工作正常,直到我达到以下记录:
B002VECGTG,B002VECGTG,拥有17131个空间射手,“4426”,0.04%,4832%,0.03%,0%,1,0.02%,20.47美元,1
在“4426”和“4426”中,转义的命令阻止了我的解析器
这是我用来解析文本行的内容:
char[] comma = { ',' };
string[] words = line.Split(comma);
如何防止程序中断?您不能仅使用逗号拆分。要为这种情况实现适当的解析器,您需要自己循环字符串,跟踪是否在引号内。如果您在一个带引号的字符串中,则应继续,直到找到另一个引号
IEnumerable<string> LineSplitter(string line)
{
int fieldStart = 0;
for(int i = 0; i < line.Length; i++)
{
if(line[i] == ',')
{
yield return line.SubString(fieldStart, i - fieldStart);
fieldStart = i + 1;
}
if(line[i] == '"')
for(i++; line[i] != '"'; i++) {}
}
}
IEnumerable行拆分器(字符串行)
{
int fieldStart=0;
for(int i=0;i
我建议使用CSV解析器,而不是自己尝试解析
正如您已经发现的,正确解析CSV有一些细微差别
有许多第三方软件(其中一些是免费的),甚至有一个内置在Visual Basic命名空间中,即Microsoft.VisualBasic.FileIO命名空间中。可以使用正则表达式:
List<List<String>> rows = new List<List<String>>();
MatchCollection matches = Regex.Matches(input, @"^(?:(?:\s*""(?<value>[^""]*)""\s*|(?<value>[^,]*)),)*?(?:\s*""(?>value>[^""]*)""\s*|(?<value>[^,]*))$", RegexOptions.Multiline);
foreach(Match row in matches)
{
List<String> values = new List<String>();
foreach(Capture value in row.Groups["value"].Captures)
{
values.Add(value.Value);
}
rows.Add(values);
}
列表行=新列表();
MatchCollection matches=Regex.matches(输入,@“^(?:\s*”(?[^“]*)”\s*(?[^,]*),)*?(?:\s*”(?>值>[^“]*)“\s*(?[^,]*)”,RegexOptions.Multiline);
foreach(匹配中的匹配行)
{
列表值=新列表();
foreach(在行组[“值”]中捕获值。捕获)
{
value.Add(value.value);
}
行。添加(值);
}
我并不认为这是最好的解决方案,但对于小文件(几行),这可能不是太糟糕。@kd7该解决方案使用库来解析文件,这里我尝试使用split进行解析。
TextFieldParser
-为什么它隐藏在VB命名空间中?@Anders-好问题。。。这是一门非常有用的课。不过,对于大型CSV文件,它显然很慢。我也喜欢这里的TextFieldParser
!关于使用第三方实用程序的答案,请访问(LGPL licensing)的FileHelpers库,了解一些不仅非常易于使用,而且可以作为一个很好的示例来学习和学习(如果需要的话)…这种方法喜欢切碎单词。我已经提交了一个编辑,用于编辑子字符串中的“一个一个地”错误,第二个for循环中缺少的花括号。此外,这不会从带引号的字段中删除引号,并且在调用“”时具有与拆分不同的行为。此示例从列表中删除最后一项。IEnumerable LineSplitter(string line){int fieldStart=0;for(int i=0;i