我以为这很琐碎,但我无法解决这个问题。
假设CSV文件中有一行:"Barack Obama", 48, "President", "1600 Penn Ave, Washington DC"
string[] tokens = line.split(',')
我期望这样:
"Barack Obama"
48
"President"
"1600 Penn Ave, Washington DC"
但是最后一个记号是
'Washington DC'
不是"1600 Penn Ave, Washington DC"
。是否有一种简单的方法来使split函数忽略引号内的逗号?
我无法控制CSV文件,也无法将其发送给我。客户A将使用该应用程序读取外部人员提供的文件。
最佳答案
您可能必须编写自己的split函数。
"
字符时,切换一个 bool 这是一个例子:
public static class StringExtensions
{
public static string[] SplitQuoted(this string input, char separator, char quotechar)
{
List<string> tokens = new List<string>();
StringBuilder sb = new StringBuilder();
bool escaped = false;
foreach (char c in input)
{
if (c.Equals(separator) && !escaped)
{
// we have a token
tokens.Add(sb.ToString().Trim());
sb.Clear();
}
else if (c.Equals(separator) && escaped)
{
// ignore but add to string
sb.Append(c);
}
else if (c.Equals(quotechar))
{
escaped = !escaped;
sb.Append(c);
}
else
{
sb.Append(c);
}
}
tokens.Add(sb.ToString().Trim());
return tokens.ToArray();
}
}
然后只需致电:
string[] tokens = line.SplitQuoted(',','\"');
基准测试
对我的代码和Dan Tao的代码进行基准测试的结果如下。如果有人需要,我很乐意为其他解决方案提供基准?
代码:
string input = "\"Barak Obama\", 48, \"President\", \"1600 Penn Ave, Washington DC\""; // Console.ReadLine()
string[] tokens = null;
// run tests
DateTime start = DateTime.Now;
for (int i = 0; i < 1000000; i++)
tokens = input.SplitWithQualifier(',', '\"', false);
Console.WriteLine("1,000,000 x SplitWithQualifier = {0}ms", DateTime.Now.Subtract(start).TotalMilliseconds);
start = DateTime.Now;
for (int i = 0; i<1000000;i++)
tokens = input.SplitQuoted(',', '\"');
Console.WriteLine("1,000,000 x SplitQuoted = {0}ms", DateTime.Now.Subtract(start).TotalMilliseconds);
输出:
1,000,000 x SplitWithQualifier = 8156.25ms
1,000,000 x SplitQuoted = 2406.25ms