在C#中拆分字符串

rit*_*itu 12 c#

我认为这将是微不足道的,但我不能让这个工作.

假设CSV文件中有一行: "Barack Obama", 48, "President", "1600 Penn Ave, Washington DC"

string[] tokens = line.split(',')

我期待这个:

 "Barack Obama"
 48
 "President"
 "1600 Penn Ave, Washington DC"
Run Code Online (Sandbox Code Playgroud)

但最后一个标记 'Washington DC'不是 "1600 Penn Ave, Washington DC".

是否有一种简单的方法可以让split函数忽略引号内的逗号?

我无法控制CSV文件但它没有发送给我.客户A将使用该应用程序读取外部个人提供的文件.

Dam*_*isa 14

您可能必须编写自己的拆分功能.

  • 遍历字符串中的每个字符
  • 当你点击一个"字符时,切换一个布尔值
  • 当你点击逗号时,如果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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后打电话:

string[] tokens = line.SplitQuoted(',','\"');
Run Code Online (Sandbox Code Playgroud)

基准

对我的代码和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);
Run Code Online (Sandbox Code Playgroud)

输出:

1,000,000 x SplitWithQualifier = 8156.25ms
1,000,000 x SplitQuoted =        2406.25ms
Run Code Online (Sandbox Code Playgroud)


Dan*_*Tao 11

我有一个SplitWithQualifier扩展方法,我在这里和那里使用,利用Regex.

我没有声明这段代码的健壮性,但它对我来说已经有一段时间了.

// mangled code horribly to fit without scrolling
public static class CsvSplitter
{
    public static string[] SplitWithQualifier(this string text,
                                              char delimiter,
                                              char qualifier,
                                              bool stripQualifierFromResult)
    {
        string pattern = string.Format(
            @"{0}(?=(?:[^{1}]*{1}[^{1}]*{1})*(?![^{1}]*{1}))",
            Regex.Escape(delimiter.ToString()),
            Regex.Escape(qualifier.ToString())
        );

        string[] split = Regex.Split(text, pattern);

        if (stripQualifierFromResult)
            return split.Select(s => s.Trim().Trim(qualifier)).ToArray();
        else
            return split;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

string csv = "\"Barak Obama\", 48, \"President\", \"1600 Penn Ave, Washington DC\"";
string[] values = csv.SplitWithQualifier(',', '\"', true);

foreach (string value in values)
    Console.WriteLine(value);
Run Code Online (Sandbox Code Playgroud)

输出:

Barak Obama
48
President
1600 Penn Ave, Washington DC
Run Code Online (Sandbox Code Playgroud)


Amr*_*mry 5

我从大局看到你实际上是在尝试解析CSV输入.因此,我建议您使用CSV解析器来执行此类操作,而不是建议如何正确地拆分字符串.

快速CSV阅读器

我建议的是可从此CodeProject页面获取的库(可用源代码):http://www.codeproject.com/KB/database/CsvReader.aspx

我亲自使用它并喜欢它.它是一个.NET本机代码,比使用OLEDB快得多(它也可以为你做CSV解析,但相信我,它很慢).