Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解析C#中的CSV文件,带有头_C#_Csv_File Io_Io_Header - Fatal编程技术网

解析C#中的CSV文件,带有头

解析C#中的CSV文件,带有头,c#,csv,file-io,io,header,C#,Csv,File Io,Io,Header,是否有默认/官方/推荐的方法来解析C#中的CSV文件?我不想使用自己的解析器 此外,我还看到过一些人使用ODBC/OLEDB通过文本驱动程序读取CSV的例子,很多人都不赞成这样做,因为它有“缺点”。这些缺点是什么 理想情况下,我正在寻找一种通过列名读取CSV的方法,使用第一条记录作为标题/字段名。给出的一些答案是正确的,但基本上可以将文件反序列化为类。让库为您处理所有的细节!:-) 检查并保持干燥-不要重复你自己-无需第无数次重新发明车轮 基本上,您只需要通过一个公共类(以及经过深思熟虑的属性,

是否有默认/官方/推荐的方法来解析C#中的CSV文件?我不想使用自己的解析器

此外,我还看到过一些人使用ODBC/OLEDB通过文本驱动程序读取CSV的例子,很多人都不赞成这样做,因为它有“缺点”。这些缺点是什么


理想情况下,我正在寻找一种通过列名读取CSV的方法,使用第一条记录作为标题/字段名。给出的一些答案是正确的,但基本上可以将文件反序列化为类。

让库为您处理所有的细节!:-)

检查并保持干燥-不要重复你自己-无需第无数次重新发明车轮


基本上,您只需要通过一个公共类(以及经过深思熟虑的属性,如默认值、空值替换等)定义数据的形状(CSV中各行中的字段),将FileHelpers引擎指向一个文件,答对了,您从该文件中返回了所有条目。一个简单的操作-伟大的性能

如果您只需要读取csv文件,我建议您使用以下库:
如果您还需要生成csv文件,请使用此文件:


它们都是免费的、开源的。

在商业应用程序中,我使用codeproject.com上的开源项目

它工作正常,性能良好。在我提供的链接上有一些基准测试

从项目页面复制的一个简单示例:

using (CsvReader csv = new CsvReader(new StreamReader("data.csv"), true))
{
    int fieldCount = csv.FieldCount;
    string[] headers = csv.GetFieldHeaders();

    while (csv.ReadNextRecord())
    {
        for (int i = 0; i < fieldCount; i++)
            Console.Write(string.Format("{0} = {1};", headers[i], csv[i]));

        Console.WriteLine();
    }
}
使用(CsvReader csv=new CsvReader(new StreamReader(“data.csv”),true))
{
int fieldCount=csv.fieldCount;
string[]headers=csv.GetFieldHeaders();
而(csv.ReadNextRecord())
{
对于(int i=0;i
正如您所见,使用它非常简单。

(我维护的库)将CSV文件读入自定义对象

var csv = new CsvReader( File.OpenText( "file.csv" ) );
var myCustomObjects = csv.GetRecords<MyCustomObject>();

这里有一个我经常使用的助手类,以防有人回到这个线程(我想分享它)

我使用它是为了将其移植到随时可用的项目中:

public class CSVHelper : List<string[]>
{
  protected string csv = string.Empty;
  protected string separator = ",";

  public CSVHelper(string csv, string separator = "\",\"")
  {
    this.csv = csv;
    this.separator = separator;

    foreach (string line in Regex.Split(csv, System.Environment.NewLine).ToList().Where(s => !string.IsNullOrEmpty(s)))
    {
      string[] values = Regex.Split(line, separator);

      for (int i = 0; i < values.Length; i++)
      {
        //Trim values
        values[i] = values[i].Trim('\"');
      }

      this.Add(values);
    }
  }
}
公共类CSVHelper:列表
{
受保护字符串csv=string.Empty;
受保护的字符串分隔符=“,”;
公共CSVHelper(字符串csv,字符串分隔符=“\”,\”)
{
this.csv=csv;
this.separator=分隔符;
foreach(Regex.Split(csv,System.Environment.NewLine).ToList()中的字符串行,其中(s=>!string.IsNullOrEmpty)
{
字符串[]值=Regex.Split(行,分隔符);
for(int i=0;i
然后像这样使用它:

public List<Person> GetPeople(string csvContent)
{
  List<Person> people = new List<Person>();
  CSVHelper csv = new CSVHelper(csvContent);
  foreach(string[] line in csv)
  {
    Person person = new Person();
    person.Name = line[0];
    person.TelephoneNo = line[1];
    people.Add(person);
  }
  return people;
}
public List GetPeople(字符串csvContent)
{
列表人员=新列表();
CSVHelper csv=新的CSVHelper(csv内容);
foreach(csv中的字符串[]行)
{
Person=新人();
person.Name=行[0];
person.TelephoneNo=行[1];
人。添加(人);
}
还人,;
}

[更新的csv帮助程序:修复了上一个新行字符创建新行的错误]

我知道有点晚了,但刚刚找到一个库
Microsoft.VisualBasic.FileIO
,它有
TextFieldParser
类来处理csv文件。

csv解析器现在是.NET Framework的一部分

添加对Microsoft.VisualBasic.dll的引用(在C#中工作正常,不介意名称)

文件在这里-

另外,如果您需要CSV导出器,请尝试(discl:我是贡献者之一)

它是根据MIT许可证发布的:

您可以使用安装它。在中运行以下命令

用法 假设我们在一个CSV文件
Persons.CSV
中有一组人,他们的名字、姓氏和出生日期

FirstName;LastName;BirthDate
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02
系统中相应的域模型可能如下所示

私人阶级人士
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共日期时间出生日期{get;set;}
}
使用TinyCsvParser时,必须定义CSV数据中的列与域模型中的属性之间的映射

私有类CsvPersonMapping:CsvMapping
{
公共CsvPersonMapping()
:base()
{
MapProperty(0,x=>x.FirstName);
MapProperty(1,x=>x.LastName);
MapProperty(2,x=>x.生日);
}
}
然后,我们可以使用映射使用
CsvParser
解析CSV数据

namespace TinyCsvParser.Test
{
[测试夹具]
公共类TinyCsvParserTest
{
[测试]
公共无效TinyCsvTest()
{
CsvParserOptions CsvParserOptions=新的CsvParserOptions(true,new[]{';'});
CsvPersonMapping csvMapper=新的CsvPersonMapping();
CsvParser CsvParser=新的CsvParser(csvParserOptions,csvMapper);
var结果=csvParser
.ReadFromFile(@“persons.csv”,Encoding.ASCII)
.ToList();
Assert.AreEqual(2,result.Count);
Assert.IsTrue(result.All(x=>x.IsValid));
Assert.AreEqual(“Philipp”,结果[0].result.FirstName);
Assert.AreEqual(“Wagner”,结果[0].result.LastName);
Assert.AreEqual(1986年,结果[0].result.BirthDate.Year);
Assert.AreEqual(5,结果[0].result.BirthDate.Month);
Assert.AreEqual(12,结果[0].result.BirthDate.Day);
Assert.AreEqual(“Max”,结果[1].result.FirstName);
Assert.AreEqual(“Mustermann”,result[1].result.LastName);
Assert.AreEqual(2014,结果[1]。结果。出生日期。年份);
Assert.AreEqual(1,结果[1].result.BirthDate.Month);
public List<Person> GetPeople(string csvContent)
{
  List<Person> people = new List<Person>();
  CSVHelper csv = new CSVHelper(csvContent);
  foreach(string[] line in csv)
  {
    Person person = new Person();
    person.Name = line[0];
    person.TelephoneNo = line[1];
    people.Add(person);
  }
  return people;
}
using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    while (!parser.EndOfData)
    {
        //Process row
        string[] fields = parser.ReadFields();
        foreach (string field in fields)
        {
            //TODO: Process field
        }
    }
}
PM> Install-Package TinyCsvParser
FirstName;LastName;BirthDate
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02
string[] tokens = System.Text.RegularExpressions.Regex.Split(paramString, ",");
    using Microsoft.VisualBasic.FileIO;

    public static List<List<string>> ParseCSV (string csv)
    {
        List<List<string>> result = new List<List<string>>();


        // To use the TextFieldParser a reference to the Microsoft.VisualBasic assembly has to be added to the project. 
        using (TextFieldParser parser = new TextFieldParser(new StringReader(csv))) 
        {
            parser.CommentTokens = new string[] { "#" };
            parser.SetDelimiters(new string[] { ";" });
            parser.HasFieldsEnclosedInQuotes = true;

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

            while (!parser.EndOfData)
            {
                var values = new List<string>();

                var readFields = parser.ReadFields();
                if (readFields != null)
                    values.AddRange(readFields);
                result.Add(values);
            }
        }

        return result;
    }
using System;
using System.Collections.Generic;
using System.Text;

class CsvParser
{
    public static List<string> Parse(string line)
    {
        const char escapeChar = '"';
        const char splitChar = ',';
        bool inEscape = false;
        bool priorEscape = false;

        List<string> result = new List<string>();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < line.Length; i++)
        {
            char c = line[i];
            switch (c)
            {
                case escapeChar:
                    if (!inEscape)
                        inEscape = true;
                    else
                    {
                        if (!priorEscape)
                        {
                            if (i + 1 < line.Length && line[i + 1] == escapeChar)
                                priorEscape = true;
                            else
                                inEscape = false;
                        }
                        else
                        {
                            sb.Append(c);
                            priorEscape = false;
                        }
                    }
                    break;
                case splitChar:
                    if (inEscape) //if in escape
                        sb.Append(c);
                    else
                    {
                        result.Add(sb.ToString());
                        sb.Length = 0;
                    }
                    break;
                default:
                    sb.Append(c);
                    break;
            }
        }

        if (sb.Length > 0)
            result.Add(sb.ToString());

        return result;
    }

}
Csv csv = new Csv("\t");//delimiter symbol

csv.FileOpen("c:\\file1.csv");

var row1Cell6Value = csv.Rows[0][5];

csv.AddRow("asdf","asdffffff","5")

csv.FileSave("c:\\file2.csv");
public static DataTable ReadCsv(string path)
{
    DataTable result = new DataTable("SomeData");
    using (TextFieldParser parser = new TextFieldParser(path))
    {
        parser.TextFieldType = FieldType.Delimited;
        parser.SetDelimiters(",");
        bool isFirstRow = true;
        //IList<string> headers = new List<string>();

        while (!parser.EndOfData)
        {
            string[] fields = parser.ReadFields();
            if (isFirstRow)
            {
                foreach (string field in fields)
                {
                    result.Columns.Add(new DataColumn(field, typeof(string)));
                }
                isFirstRow = false;
            }
            else
            {
                int i = 0;
                DataRow row = result.NewRow();
                foreach (string field in fields)
                {
                    row[i++] = field;
                }
                result.Rows.Add(row);
            }
        }
    }
    return result;
}
string csv = @"Id, Name
1, Carl
2, Tom
3, Mark";

using (var p = ChoCSVReader.LoadText(csv)
    .WithFirstLineHeader()
    )
{
    foreach (var rec in p)
    {
        Console.WriteLine($"Id: {rec.Id}");
        Console.WriteLine($"Name: {rec.Name}");
    }
}
public partial class EmployeeRec
{
    public int Id { get; set; }
    public string Name { get; set; }
}

static void CSVTest()
{
    string csv = @"Id, Name
1, Carl
2, Tom
3, Mark";

    using (var p = ChoCSVReader<EmployeeRec>.LoadText(csv)
        .WithFirstLineHeader()
        )
    {
        foreach (var rec in p)
        {
            Console.WriteLine($"Id: {rec.Id}");
            Console.WriteLine($"Name: {rec.Name}");
        }
    }
}
void Main()
{
    var file1 = "a,b,c\r\nx,y,z";
    CSV.ParseText(file1).Dump();

    var file2 = "a,\"b\",c\r\nx,\"y,z\"";
    CSV.ParseText(file2).Dump();

    var file3 = "a,\"b\",c\r\nx,\"y\r\nz\"";
    CSV.ParseText(file3).Dump();

    var file4 = "\"\"\"\"";
    CSV.ParseText(file4).Dump();
}

static class CSV
{
    public struct Record
    {
        public readonly string[] Row;

        public string this[int index] => Row[index];

        public Record(string[] row)
        {
            Row = row;
        }
    }

    public static List<Record> ParseText(string text)
    {
        return Parse(new StringReader(text));
    }

    public static List<Record> ParseFile(string fn)
    {
        using (var reader = File.OpenText(fn))
        {
            return Parse(reader);
        }
    }

    public static List<Record> Parse(TextReader reader)
    {
        var data = new List<Record>();

        var col = new StringBuilder();
        var row = new List<string>();
        for (; ; )
        {
            var ln = reader.ReadLine();
            if (ln == null) break;
            if (Tokenize(ln, col, row))
            {
                data.Add(new Record(row.ToArray()));
                row.Clear();
            }
        }

        return data;
    }

    public static bool Tokenize(string s, StringBuilder col, List<string> row)
    {
        int i = 0;

        if (col.Length > 0)
        {
            col.AppendLine(); // continuation

            if (!TokenizeQuote(s, ref i, col, row))
            {
                return false;
            }
        }

        while (i < s.Length)
        {
            var ch = s[i];
            if (ch == ',')
            {
                row.Add(col.ToString().Trim());
                col.Length = 0;
                i++;
            }
            else if (ch == '"')
            {
                i++;
                if (!TokenizeQuote(s, ref i, col, row))
                {
                    return false;
                }
            }
            else
            {
                col.Append(ch);
                i++;
            }
        }

        if (col.Length > 0)
        {
            row.Add(col.ToString().Trim());
            col.Length = 0;
        }

        return true;
    }

    public static bool TokenizeQuote(string s, ref int i, StringBuilder col, List<string> row)
    {
        while (i < s.Length)
        {
            var ch = s[i];
            if (ch == '"')
            {
                // escape sequence
                if (i + 1 < s.Length && s[i + 1] == '"')
                {
                    col.Append('"');
                    i++;
                    i++;
                    continue;
                }
                i++;
                return true;
            }
            else
            {
                col.Append(ch);
                i++;
            }
        }
        return false;
    }
}
    public static string FormatCSV(List<string> parts)
    {
        string result = "";

        foreach (string s in parts)
        {
            if (result.Length > 0)
            {
                result += ",";

                if (s.Length == 0)
                    continue;
            }

            if (s.Length > 0)
            {
                result += "\"" + s.Replace("\"", "\"\"") + "\"";
            }
            else
            {
                // cannot output double quotes since its considered an escape for a quote
                result += ",";
            }
        }

        return result;
    }

    enum CSVMode
    {
        CLOSED = 0,
        OPENED_RAW = 1,
        OPENED_QUOTE = 2
    }

    public static List<string> ParseCSV(string input)
    {
        List<string> results;

        CSVMode mode;

        char[] letters;

        string content;


        mode = CSVMode.CLOSED;

        content = "";
        results = new List<string>();
        letters = input.ToCharArray();

        for (int i = 0; i < letters.Length; i++)
        {
            char letter = letters[i];
            char nextLetter = '\0';

            if (i < letters.Length - 1)
                nextLetter = letters[i + 1];

            // If its a quote character
            if (letter == '"')
            {
                // If that next letter is a quote
                if (nextLetter == '"' && mode == CSVMode.OPENED_QUOTE)
                {
                    // Then this quote is escaped and should be added to the content

                    content += letter;

                    // Skip the escape character
                    i++;
                    continue;
                }
                else
                {
                    // otherwise its not an escaped quote and is an opening or closing one
                    // Character is skipped

                    // If it was open, then close it
                    if (mode == CSVMode.OPENED_QUOTE)
                    {
                        results.Add(content);

                        // reset the content
                        content = "";

                        mode = CSVMode.CLOSED;

                        // If there is a next letter available
                        if (nextLetter != '\0')
                        {
                            // If it is a comma
                            if (nextLetter == ',')
                            {
                                i++;
                                continue;
                            }
                            else
                            {
                                throw new Exception("Expected comma. Found: " + nextLetter);
                            }
                        }
                    }
                    else if (mode == CSVMode.OPENED_RAW)
                    {
                        // If it was opened raw, then just add the quote 
                        content += letter;
                    }
                    else if (mode == CSVMode.CLOSED)
                    {
                        // Otherwise open it as a quote 

                        mode = CSVMode.OPENED_QUOTE;
                    }
                }
            }
            // If its a comma seperator
            else if (letter == ',')
            {
                // If in quote mode
                if (mode == CSVMode.OPENED_QUOTE)
                {
                    // Just read it
                    content += letter;
                }
                // If raw, then close the content
                else if (mode == CSVMode.OPENED_RAW)
                {
                    results.Add(content);

                    content = "";

                    mode = CSVMode.CLOSED;
                }
                // If it was closed, then open it raw
                else if (mode == CSVMode.CLOSED)
                {
                    mode = CSVMode.OPENED_RAW;

                    results.Add(content);

                    content = "";
                }
            }
            else
            {
                // If opened quote, just read it
                if (mode == CSVMode.OPENED_QUOTE)
                {
                    content += letter;
                }
                // If opened raw, then read it
                else if (mode == CSVMode.OPENED_RAW)
                {
                    content += letter;
                }
                // It closed, then open raw
                else if (mode == CSVMode.CLOSED)
                {
                    mode = CSVMode.OPENED_RAW;

                    content += letter;
                }
            }
        }

        // If it was still reading when the buffer finished
        if (mode != CSVMode.CLOSED)
        {
            results.Add(content);
        }

        return results;
    }
                using (TextFieldParser parser = new TextFieldParser(outputLocation))
                 {
                        parser.TextFieldType = FieldType.Delimited;
                        parser.SetDelimiters(",");
                        string[] headers = parser.ReadLine().Split(',');
                        foreach (string header in headers)
                        {
                            dataTable.Columns.Add(header);
                        }
                        while (!parser.EndOfData)
                        {
                            string[] fields = parser.ReadFields();
                            dataTable.Rows.Add(fields);
                        }
                    }