TextFieldParser从字符串而不是文件解析CSV

时间:2016-03-24 20:32:41

标签: c# csv textfieldparser

使用Microsoft.VisualBasic.FileIO中的TextFieldParser,可以解析如下所示的CSV文件:

using (TextFieldParser parser = new TextFieldParser(CSVPath))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    parser.HasFieldsEnclosedInQuotes = true;
    while (!parser.EndOfData) { string[] fields = parser.ReadFields(); }
}

但是,这依赖于使用CSV文件路径初始化TextFieldParser。是否可以在传递包含数据记录本身的字符串时具有相同的效果?

例如,对于保存在字符串变量中的值为Data1,6.5,"Data3 ""MoreData"""的CSV数据记录(请注意由于转义引号而引用的最后一个数据),我可以将数据转换为字符串数组,如这样:

[0] = "Data1"
[1] = "6.5"
[2] = "Data3 \"MoreData\""

3 个答案:

答案 0 :(得分:10)

包含原始字符串的StringReader可以传递给新的TextFieldParser并以相同的方式处理。

StringReader sr = new StringReader("Data1,6.5,\"Data3,\"\"MoreData\"\"\"");
using (var parser = new TextFieldParser(sr))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    parser.HasFieldsEnclosedInQuotes = true;
    while (!parser.EndOfData)
    {
        Console.WriteLine("Line:");
        var fields = parser.ReadFields();
        foreach (var field in fields)
        {
            Console.WriteLine("\tField: " + field);
        }
    }
}

输出到控制台:

Line:
    Field: Data1
    Field: 6.5
    Field: Data3,"MoreData"

答案 1 :(得分:7)

您还可以从Stream或TextReader实例化TextFieldParser。它不一定是字符串路径。因此,只要您可以将其放入流中,您就可以将它真正地流式传输。可能只是一个MemoryStream。

https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser%28v=vs.110%29.aspx

E.g。

using (var stream = new MemoryStream())
{
    var input = "A, B, C, D\r\n";
    input += "Jeremy,Paul,Linda,Joe\r\n";
    var bytes = System.Text.Encoding.Default.GetBytes(input);
    stream.Write(bytes, 0, bytes.Length);
    stream.Seek(0, SeekOrigin.Begin);
    using (var parser = new TextFieldParser(stream))
    {
        parser.TextFieldType = FieldType.Delimited;
        parser.SetDelimiters(",");
        parser.HasFieldsEnclosedInQuotes = true;
        while (!parser.EndOfData)
        {
            Console.WriteLine("Line:");
            var fields = parser.ReadFields();
            foreach (var field in fields)
            {
                Console.WriteLine("\tField: " + field);
            }
        }
    }
}

答案 2 :(得分:0)

使用TextFieldParser是最容易,最简单的方法,并且如公认的答案所述,您完全可以从流中实例化它。

尽管如此,我还是想为所有在G ** gle搜索后到达这里的人提供有价值的信息,以完成被接受的答案:

我发现一个非常简单的解析器可以通过这段代码读取CSV数据:

var res = new List<string[]>();

using (TextFieldParser parser = new TextFieldParser(filepath))
{
    parser.CommentTokens = new string[] { "#" };
    parser.SetDelimiters(new string[] { ";" });
    parser.HasFieldsEnclosedInQuotes = true;

    // Skip over header line.
    parser.ReadLine();

    while (!parser.EndOfData)
    {
        res.Add(parser.ReadFields());
    }
}

请务必谨慎使用parser.ReadLine(),因为如果标头字段中至少有一个字段包含CRLF,它可能会产生不需要的结果。 在这种情况下,您的第一个读取行将在第一个CRLF之后立即包含标题的其余部分。

因此请注意,最好使用ReadFields读取整个文件,该字段要很好地处理格式良好的字段(请参见https://tools.ietf.org/html/rfc4180的CSV RFC),包括标头,如果出现第一行,则忽略第一行需要。

4180 RFC已经足够完善,如果您也想实现适当的CSV编写器,那么它为您提供了解决之道。

与CSV小伙子玩得开心。