Zephni
Zephni

Reputation: 873

Delimit a string by character unless within quotation marks C#

I need to demilitarise text by a single character, a comma. But I want to only use that comma as a delimiter if it is not encapsulated by quotation marks.

An example:

Method,value1,value2

Would contain three values: Method, value1 and value2

But:

Method,"value1,value2"

Would contain two values: Method and "value1,value2"

I'm not really sure how to go about this as when splitting a string I would use:

String.Split(',');

But that would demilitarise based on ALL commas. Is this possible without getting overly complicated and having to manually check every character of the string.

Thanks in advance

Upvotes: 1

Views: 986

Answers (2)

Shar1er80
Shar1er80

Reputation: 9041

You can try Regex.Split() to split the data up using the pattern

",|(\"[^\"]*\")" 

This will split by commas and by characters within quotes.

Code Sample:

using System;
using System.Linq;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        string data = "Method,\"value1,value2\",Method2";
        string[] pieces = Regex.Split(data, ",|(\"[^\"]*\")").Where(exp => !String.IsNullOrEmpty(exp)).ToArray();

        foreach (string piece in pieces)
        {
            Console.WriteLine(piece);
        }
    }
}

Results:

Method
"value1,value2"
Method2

Demo

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460288

Copied from my comment: Use an available csv parser like VisualBasic.FileIO.TextFieldParser or this or this.

As requested, here is an example for the TextFieldParser:

var allLineFields = new List<string[]>();
string sampleText = "Method,\"value1,value2\"";
var reader = new System.IO.StringReader(sampleText);
using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(reader))
{
    parser.Delimiters = new string[] { "," };
    parser.HasFieldsEnclosedInQuotes = true; // <--- !!!
    string[] fields;
    while ((fields = parser.ReadFields()) != null)
    {
        allLineFields.Add(fields);
    }
}

This list now contains a single string[] with two strings. I have used a StringReader because this sample uses a string, if the source is a file use a StreamReader(f.e. via File.OpenText).

Upvotes: 2

Related Questions