Use an algorithm like this:
Process each character of each line one at a time.
Count every " that you find.
If the number of "s is odd, you know that you need to keep reading the current field until you hit another ".
If the number of "s is even, you know that as soon as you hit a space you're on to the next field.
Something like (this may have errors - I've just written it off the top of my head):
StringBuilder field = new StringBuilder();
int quoteCount = 0;
foreach (char c in line)
{
if (c == '"')
{
quotCount++;
continue;
}
if (quoteCount % 2 = 0)
{
if (c == ' ')
{
yield return field.ToString();
field.Length = 0;
}
else
{
field.Append(c);
}
}
else
{
field.Append(c);
}
}
EDIT:
Here's a hacky example that works for your sample - the GetFields method needs some refactoring and it's far from the quality of anything I'd put in my code, but the basic principle is there.
class Program
{
static void Main(string[] args)
{
var records = ReadFile(@"D:\x.txt");
foreach (var record in records)
{
foreach (var field in record)
{
Console.Write(field + " | ");
}
Console.WriteLine();
}
Console.ReadKey();
}
static IEnumerable<IEnumerable<String>> ReadFile(String file)
{
using (var reader = new StreamReader(file))
{
// Ignore column titles line.
reader.ReadLine();
while (!reader.EndOfStream)
{
yield return GetFields(reader.ReadLine());
}
}
}
static IEnumerable<String> GetFields(String line)
{
Int32 quoteCount = 0;
StringBuilder field = new StringBuilder();
foreach (var c in line)
{
if (c == '"')
{
quoteCount++;
continue;
}
if (quoteCount % 2 == 0)
{
if (c == ' ')
{
if (field.Length > 0)
{
yield return field.ToString();
field.Length = 0;
}
}
else
{
field.Append(c);
}
}
else
{
field.Append(c);
}
}
yield return field.ToString();
}
}