[英]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將使用該應用程序讀取外部個人提供的文件。
您可能必須編寫自己的拆分功能。
"
字符時,切換一個布爾值 這是一個例子:
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解析器來執行此類操作,而不是建議如何正確拆分字符串。
我建議的是可從此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.