我知道如何从一个字符串中获取子字符串,这些字符串是昏迷分离的,但这里有一个复杂因素:如果substring包含昏迷,该怎么办。
如果子字符串包含逗号,新行或双引号,则整个子字符串将用双引号封装。
如果子字符串包含双引号,则双引号将使用另一个双引号进行转义。 最糟糕的情况是,如果我有这样的事情:
first,"second, second","""third"" third","""fourth"", fourth"
在这种情况下,子串是:
第二个,第二个用双引号封装,我不希望列表/数组中的那些双引号。
“third”第三个用双引号封装,因为它包含双引号,并且使用aditional双引号进行转义。我再次不希望在列表/数组中封装双引号,我不希望双引号转义为双引号,但我想要原始双引号,它是子字符串的一部分。
答案 0 :(得分:4)
使用TextFieldParser
的一种方式:
using (var reader = new StringReader("first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\""))
using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(reader))
{
parser.Delimiters = new[] { "," };
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
foreach (var field in parser.ReadFields())
Console.WriteLine(field);
}
}
有关
first
second, second
"third" third
"fourth", fourth
答案 1 :(得分:0)
试试这个
string input = "first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\"";
string[] output = input.Split(new string[] {"\",\""}, StringSplitOptions.RemoveEmptyEntries);

答案 2 :(得分:0)
我建议你为这个问题构建一个小型状态机。你会有像:
这样的州这肯定会正确读取CSV。您还可以使分隔符可配置,以便支持TSV或以分号分隔的格式。
另请注意CSV格式中一个非常重要的情况:引用字段可能包含新行!另一个值得注意的特殊情况:空场(如:,,)。
答案 3 :(得分:0)
这不是最优雅的解决方案,但它可能对您有所帮助。我会遍历字符并对引号进行奇数计数。例如,如果您遇到奇数引号则为true,对于偶数引号则为false。
当此bool值为true时遇到的任何逗号都不应被视为分隔符。如果您知道它是一个分隔符,您可以使用该信息执行多项操作。下面我用更易于管理的东西替换了分隔符(虽然效率不高):
bool odd = false;
char replacementDelimiter = "|"; // Or some very unlikely character
for(int i = 0; i < str.len; ++i)
{
if(str[i] == '\"')
odd = !odd;
else if (str[i] == ',')
{
if(!odd)
str[i] = replacementDelimiter;
}
}
string[] commaSeparatedTokens = str.Split(replacementDelimiter);
此时你应该有一个字符串数组,这些字符串在你想要的逗号上分开。从这里开始,处理报价会更简单。
我希望这可以帮到你。
答案 4 :(得分:0)
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApp
{
class Program
{
private static IEnumerable<string> Parse(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
// empty string => nothing to do
yield break;
}
int count = input.Length;
StringBuilder sb = new StringBuilder();
int j;
for (int i = 0; i < count; i++)
{
char c = input[i];
if (c == ',')
{
yield return sb.ToString();
sb.Clear();
}
else if (c == '"')
{
// begin quoted string
sb.Clear();
for (j = i + 1; j < count; j++)
{
if (input[j] == '"')
{
// quote
if (j < count - 1 && input[j + 1] == '"')
{
// double quote
sb.Append('"');
j++;
}
else
{
break;
}
}
else
{
sb.Append(input[j]);
}
}
yield return sb.ToString();
// clear buffer and skip to next comma
sb.Clear();
for (i = j + 1; i < count && input[i] != ','; i++) ;
}
else
{
sb.Append(c);
}
}
}
[STAThread]
static void Main(string[] args)
{
foreach (string str in Parse("first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\""))
{
Console.WriteLine(str);
}
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
答案 5 :(得分:0)
感谢您的回答,但在我看到它们之前,我写了这个解决方案,它并不漂亮,但它对我有用。
string line = "first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\"";
var substringArray = new List<string>();
string substring = null;
var doubleQuotesCount = 0;
for (var i = 0; i < line.Length; i++)
{
if (line[i] == ',' && (doubleQuotesCount % 2) == 0)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
continue;
}
else
{
if (line[i] == '"')
doubleQuotesCount++;
substring += line[i];
//If it is a last character
if (i == line.Length - 1)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
}
}
}
for(var i = 0; i < substringArray.Count; i++)
{
if (substringArray[i] != null)
{
//remove first double quote
if (substringArray[i][0] == '"')
{
substringArray[i] = substringArray[i].Substring(1);
}
//remove last double quote
if (substringArray[i][substringArray[i].Length - 1] == '"')
{
substringArray[i] = substringArray[i].Remove(substringArray[i].Length - 1);
}
//Replace double double quotes with single double quote
substringArray[i] = substringArray[i].Replace("\"\"", "\"");
}
}