如何在引号之间忽略逗号而拆分(',')字符串?

时间:2014-01-24 21:37:46

标签: c# string split

我在字符串上使用.Split(',')方法,我知道这些字符串以逗号分隔,我希望将这些值分开并放入string[]对象中。这适用于这样的字符串:

78,969.82,GW440,

但是当第二个值超过1000时,值开始变得不同,就像在这个例子中找到的那样:

79,"1,013.42",GW450,...

这些值来自电子表格控件,我在其中使用ExportToCsv(...)方法中构建的控件,这解释了为什么实际数值的格式化版本。

问题

有没有办法让.Split(',')方法忽略引号内的逗号?我实际上并不希望将值"1,013.42"拆分为"1013.42"

有什么想法吗?谢谢!

更新

我真的很想在不使用第三方工具的情况下这样做,因为我的用例实际上并没有涉及除此之外的许多其他情况,即使它是我工作解决方案的一部分,也有一个类似于工具的工具。现在真的让任何人受益。我希望有一些东西可以快速解决我丢失的这个特殊用例,但是现在是周末,我会看到周一我能不能再给这个问题多一次更新了解决方案我最终来了起来。到目前为止,谢谢大家的帮助,我将在周一进一步评估每个答案。

3 个答案:

答案 0 :(得分:11)

这是我们在这里的一些项目中使用的相当直接的CSV阅读器实现。易于使用并处理您正在谈论的案例。

首先是CSV类

public static class Csv
{
    public static string Escape(string s)
    {
        if (s.Contains(QUOTE))
            s = s.Replace(QUOTE, ESCAPED_QUOTE);

        if (s.IndexOfAny(CHARACTERS_THAT_MUST_BE_QUOTED) > -1)
            s = QUOTE + s + QUOTE;

        return s;
    }

    public static string Unescape(string s)
    {
        if (s.StartsWith(QUOTE) && s.EndsWith(QUOTE))
        {
            s = s.Substring(1, s.Length - 2);

            if (s.Contains(ESCAPED_QUOTE))
                s = s.Replace(ESCAPED_QUOTE, QUOTE);
        }

        return s;
    }


    private const string QUOTE = "\"";
    private const string ESCAPED_QUOTE = "\"\"";
    private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };

}

然后一个非常好的Reader实现 - 如果你需要它。只需上面的CSV类,您就可以完成所需的操作。

public sealed class CsvReader : System.IDisposable
{
    public CsvReader(string fileName)
        : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
    {
    }

    public CsvReader(Stream stream)
    {
        __reader = new StreamReader(stream);
    }

    public System.Collections.IEnumerable RowEnumerator
    {
        get
        {
            if (null == __reader)
                throw new System.ApplicationException("I can't start reading without CSV input.");

            __rowno = 0;
            string sLine;
            string sNextLine;

            while (null != (sLine = __reader.ReadLine()))
            {
                while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
                    sLine += "\n" + sNextLine;

                __rowno++;
                string[] values = rexCsvSplitter.Split(sLine);

                for (int i = 0; i < values.Length; i++)
                    values[i] = Csv.Unescape(values[i]);

                yield return values;
            }

            __reader.Close();
        }

    }

    public long RowIndex { get { return __rowno; } }

    public void Dispose()
    {
        if (null != __reader) __reader.Dispose();
    }

    //============================================


    private long __rowno = 0;
    private TextReader __reader;
    private static Regex rexCsvSplitter = new Regex(@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))");
    private static Regex rexRunOnLine = new Regex(@"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$");

}

然后你可以像这样使用它。

var reader = new CsvReader(new FileStream(file, FileMode.Open));

注意:这会打开现有的CSV文件,但可以非常轻松地进行修改,以便根据需要选择string[]

答案 1 :(得分:3)

由于您正在阅读CSV文件,因此最好的做法是使用现有的CSV阅读器。除了引号之间的逗号之外,CSV还有更多内容。找到你需要处理的所有案例将是更多的工作而不是它的价值。

Here's a CSV reader question on SO.

答案 2 :(得分:0)

你应该阅读这篇文章:Regular Expression for Comma Based Splitting Ignoring Commas inside Quotes 虽然它适用于Java,但正则表达式是相同的。