12

使用 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\""
4

3 回答 3

27

可以将包含原始字符串的 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"
于 2016-03-24T21:58:50.317 回答
8

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

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

例如

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);
            }
        }
    }
}
于 2016-03-24T20:38:15.623 回答
-1

使用 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://www.rfc-editor.org/rfc/rfc4180上的 CSV RFC ),包括标题,然后在需要时忽略您的第一行。

如果您也想实现一个合适的 CSV 编写器,4180 RFC 已经足够完整,可以为您提供可行的方法。

与 CSV 家伙一起玩。

于 2020-03-27T18:36:56.557 回答