簡體   English   中英

在C#中拆分字符串

[英]Split String in C#

我認為這將是微不足道的,但我不能讓這個工作。

假設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將使用該應用程序讀取外部個人提供的文件。

您可能必須編寫自己的拆分功能。

  • 遍歷字符串中的每個字符
  • 當你點擊"字符時,切換一個布爾值
  • 當你點擊逗號時,如果bool為true,則忽略它,否則你有你的令牌

這是一個例子:

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

我有一個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;
    }
}

用法:

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

foreach (string value in values)
    Console.WriteLine(value);

輸出:

Barak Obama
48
President
1600 Penn Ave, Washington DC

我從大局看到你實際上是在嘗試解析CSV輸入。 因此,我建議您使用CSV解析器來執行此類操作,而不是建議如何正確拆分字符串。

快速CSV閱讀器

我建議的是可從此CodeProject頁面獲取的庫(可用源代碼): http//www.codeproject.com/KB/database/CsvReader.aspx

我親自使用它並喜歡它。 它是一個.NET本機代碼,比使用OLEDB快得多(它也可以為你做CSV解析,但相信我,它很慢)。

你應該使用Microsoft.VisualBasic.FileIO.TextFieldParser 它將為您正確處理所有CSV內容,請參閱: 使用TextFieldParser的示例中的類似問題

PS:不要害怕在C#項目中使用Microsoft.VisualBasic dll,它都是.NET :-)

這將是預期的行為,因為引號只是C#中的另一個字符串字符。 看起來你所追求的是引用的標記或數字標記。

我認為您可能需要使用Regex來分割字符串,除非其他人知道更好的方法。

或者你可以在一個字符串中循環遍歷字符串,一次構建字符串並以這種方式構建標記。 這是舊學校,但在您的情況下可能是最可靠的方式。

您無法使用簡單的逗號分割來解析CSV行,因為某些單元格內容將包含逗號,這些逗號不是為了描述數據,而是實際上是單元格內容本身的一部分。

這是一個簡單的基於正則表達式的C#方法的鏈接,它將您的CSV轉換為一個手動的DataTable

http://www.hotblue.com/article0000.aspx?a=0006

使用DataTables非常簡單 - 如果您需要代碼示例,請告訴我。

我建議使用正則表達式。 它將允許您以更加通用的方式提取更復雜的子串(正如您所希望的那樣)。

http://www.c-sharpcorner.com/uploadfile/prasad_1/regexppsd12062005021717am/regexppsd.aspx

http://oreilly.com/windows/archive/csharp-regular-expressions.html

你不能改變CSV的生成方式嗎? 使用OpenOffice,您可以設置char分隔符(use;)以及字符串的分隔方式(使用“或”)。

它將是這樣的:'總統';'1600 Penn Ave,華盛頓特區'

string temp = line.Replace(“\\”“,”“);

string [] tokens = temp.Split(',')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM