使用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\""
答案 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。
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小伙子玩得开心。