【问题标题】:Parsing CSV files in C#, with header在 C# 中解析带有标题的 CSV 文件
【发布时间】:2011-01-06 02:07:20
【问题描述】:

是否有默认/官方/推荐的方式来解析 C# 中的 CSV 文件?我不想滚动我自己的解析器。

此外,我还看到有人使用 ODBC/OLE DB 通过文本驱动程序读取 CSV,但由于其“缺点”,很多人不鼓励这样做。这些缺点是什么?

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

【问题讨论】:

    标签: c# csv file-io io header


    【解决方案1】:

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

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

    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
            }
        }
    }
    

    文档在这里 - TextFieldParser Class

    附:如果您需要 CSV exporter,请尝试 CsvExport(discl:我是贡献者之一)

    【讨论】:

    • 根据我的经验,TextFieldParser 在处理大型(例如 > 250Mb)文件时表现不佳。 :(
    • TextFieldParser 实现了 IDisposable,因此最好在 using 子句中使用它。否则很好回答。
    • 在构造函数中,您可能希望使用与默认编码不同的编码,如下所示: new TextFieldParser("c:\temp\test.csv", System.Text.Encoding.UTF8)
    • 如何指定csv文件是否包含标题?
    • 有没有办法在 .NET Core 中得到这个?
    【解决方案2】:

    CsvHelper(我维护的一个库)会将 CSV 文件读入自定义对象。

    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<Foo>();
    }
    

    有时您不拥有您要读取的对象。在这种情况下,您可以使用流畅的映射,因为您不能将属性放在类上。

    public sealed class MyCustomObjectMap : CsvClassMap<MyCustomObject>
    {
        public MyCustomObjectMap()
        {
            Map( m => m.Property1 ).Name( "Column Name" );
            Map( m => m.Property2 ).Index( 4 );
            Map( m => m.Property3 ).Ignore();
            Map( m => m.Property4 ).TypeConverter<MySpecialTypeConverter>();
        }
    }
    

    【讨论】:

    • 我同意@kubal5003。卖给我的是你把它作为一个 NuGet 包提供。谢谢伙计,它很快,并且可以读取我需要的所有 csv。
    • 这该死的快。在 10 秒内读取和反序列化了 130 万条记录。
    • 很棒的库很容易实现。我只是建议 Josh 在这里更新他的答案,因为自从编写了这个答案以来,库已经发生了一些变化,你不能再实例化 CsvHelper(它现在只是一个命名空间),但你必须使用 CsvReader 类。
    • knocte,现在叫ClassMap。还有其他更改,例如在请求标题记录之前必须进行读取(顺便说一下,它被设置为第一次调用 Read() 读取的任何内容)。就像其他人之前提到的那样,它超级快速且易于使用。
    • CsvHelper 也不会将所有行加载到内存中。它加载一个小缓冲区并产生结果。您可能还想提及 SoftCircuits.CsvParser 由您维护。我相信这是现在对 SO 的政策。
    【解决方案3】:

    让图书馆为您处理所有细节! :-)

    查看FileHelpers 并保持干爽 - 不要重复自己 - 无需重新发明轮子无数次......

    您基本上只需要通过公共类(以及经过深思熟虑的属性,如默认值、NULL 值替换等)来定义数据的形状 - CSV 中单独行中的字段),将 FileHelpers 引擎指向一个文件,然后宾果游戏 - 您从该文件中取回所有条目。一个简单的操作 - 出色的性能!

    【讨论】:

    • 直到您需要真正定制的东西(而且大部分都可以作为扩展来实现)FileHelpers 是迄今为止最好的方法,非常方便、经过测试且性能良好的解决方案
    • 截至 2015 年 6 月 1 日,我下载 FileHelpers 的唯一方法是在 sourceforge.net 上搜索它。这是使用的链接:sourceforge.net/projects/filehelpers/?source=directory
    • @dotnetguy 我们正在发布 3.1(目前是 3.1-rc2)。我们还重新设计了网站:www.filehelpers.net,您可以从那里下载最新版本
    • @MarcosMeli 非常感谢!我已经在我的一个项目中使用了 FileHelpers,而且使用起来轻而易举——感谢团队。我很快就计划在上面写一个博客,顺便说一句 - 喜欢这个新网站 - 干得好!
    • FileHelpers 没有正确处理 CSV 中的引号逗号,或者实际上映射字段标题,而是期望列与您的类型中声明的字段的顺序相同。我个人不会使用它。
    【解决方案4】:

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

    它运行良好,性能良好。我提供的链接上有一些基准测试。

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

    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();
        }
    }
    

    如您所见,它非常易于使用。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      【解决方案6】:

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

      我使用它是为了简单地将其移植到准备使用的项目中:

      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);
          }
        }
      }
      

      并像这样使用它:

      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;
      }
      

      [更新的 csv 助手:修复了最后一个换行符创建新行的错误]

      【讨论】:

      • 如果任何 csv 条目包含逗号 (,),此代码将不起作用。
      • 为了保持轻量,我使用管道字符作为分隔符。 '|'
      • 优秀的解决方案。只是关于第二个sn-p的问题。人是什么类型的对象
      • @CocoaDev 这是一个包含两个字符串属性的类——Name 和 TelephoneNo。只是为了这个例子。如果任何属性是整数,它应该只是一个直接的转换(带检查?)。
      【解决方案7】:

      如果您只需要阅读 csv 文件,那么我推荐这个库:A Fast CSV Reader
      如果您还需要生成 csv 文件,请使用这个:FileHelpers

      它们都是免费和开源的。

      【讨论】:

      • FileHelpers 有一个吸引人的总结:filehelpers.com FileHelpers 是一个免费且易于使用的 .NET 库,用于从文件、字符串或流中的固定长度或分隔记录导入/导出数据。
      • 虽然此链接可能会回答问题,但 Stack Overflow 不鼓励仅链接的答案,您可以通过获取链接的重要部分并将其放入您的答案来改进此答案,这样可以确保您的答案是如果链接被更改或删除,仍然是一个答案:)
      【解决方案8】:

      此解决方案使用官方 Microsoft.VisualBasic 程序集来解析 CSV。

      优点:

      • 分隔符转义
      • 忽略标题
      • 修剪空格
      • 忽略 cmets

      代码:

          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;
          }
      

      【讨论】:

        【解决方案9】:

        我为 .NET 编写了 TinyCsvParser,它是最快的 .NET 解析器之一,并且高度可配置以解析几乎任何 CSV 格式。

        它是在 MIT 许可下发布的:

        您可以使用NuGet 来安装它。在Package Manager Console中运行以下命令。

        PM> Install-Package TinyCsvParser
        

        用法

        假设我们有一个 CSV 文件 persons.csv 中的人员列表,其中包含他们的名字、姓氏和出生日期。

        FirstName;LastName;BirthDate
        Philipp;Wagner;1986/05/12
        Max;Musterman;2014/01/02
        

        我们系统中对应的领域模型可能如下所示。

        private class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public DateTime BirthDate { get; set; }
        }
        

        使用 TinyCsvParser 时,您必须定义 CSV 数据中的列与域模型中的属性之间的映射。

        private class CsvPersonMapping : CsvMapping<Person>
        {
        
            public CsvPersonMapping()
                : base()
            {
                MapProperty(0, x => x.FirstName);
                MapProperty(1, x => x.LastName);
                MapProperty(2, x => x.BirthDate);
            }
        }
        

        然后我们可以使用映射来解析带有CsvParser的CSV数据。

        namespace TinyCsvParser.Test
        {
            [TestFixture]
            public class TinyCsvParserTest
            {
                [Test]
                public void TinyCsvTest()
                {
                    CsvParserOptions csvParserOptions = new CsvParserOptions(true, new[] { ';' });
                    CsvPersonMapping csvMapper = new CsvPersonMapping();
                    CsvParser<Person> csvParser = new CsvParser<Person>(csvParserOptions, csvMapper);
        
                    var result = csvParser
                        .ReadFromFile(@"persons.csv", Encoding.ASCII)
                        .ToList();
        
                    Assert.AreEqual(2, result.Count);
        
                    Assert.IsTrue(result.All(x => x.IsValid));
        
                    Assert.AreEqual("Philipp", result[0].Result.FirstName);
                    Assert.AreEqual("Wagner", result[0].Result.LastName);
        
                    Assert.AreEqual(1986, result[0].Result.BirthDate.Year);
                    Assert.AreEqual(5, result[0].Result.BirthDate.Month);
                    Assert.AreEqual(12, result[0].Result.BirthDate.Day);
        
                    Assert.AreEqual("Max", result[1].Result.FirstName);
                    Assert.AreEqual("Mustermann", result[1].Result.LastName);
        
                    Assert.AreEqual(2014, result[1].Result.BirthDate.Year);
                    Assert.AreEqual(1, result[1].Result.BirthDate.Month);
                    Assert.AreEqual(1, result[1].Result.BirthDate.Day);
                }
            }
        }
        

        用户指南

        完整的用户指南可在以下网址获得:

        【讨论】:

          【解决方案10】:

          这是一个简短的解决方案。

                          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);
                                  }
                              }
          

          【讨论】:

            【解决方案11】:

            这是我的 KISS 实现...

            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 文件中有效。
            • Alex,John 想说的是 RFC 4180 (ietf.org/rfc/rfc4180.txt -- 参见第 2 节和第 6 项) 允许列的中间有一个 CR LF 有效地传播它在一个文件中超过 2 行。在大多数情况下,您的解决方案可能会运行良好(特别是如果 CSV 文件是通过保存 Excel 创建的),但它不涵盖这种边缘情况。上面提到的 CsvHelper 应该考虑到这种情况。
            • 是的,这是真的,但是如果您的 CSV 中有 CR LF,那么您可能不应该使用 CSV,而是使用更合适的格式,例如 json、xml 或固定长度格式。
            【解决方案12】:

            前段时间我写了一个简单的基于Microsoft.VisualBasic库的CSV读/写类。使用这个简单的类,您将能够像使用二维数组一样使用 CSV。您可以通过以下链接找到我的课程:https://github.com/ukushu/DataExporter

            简单的用法示例:

            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");
            

            对于阅读标题,您只需阅读csv.Rows[0] 单元格:)

            【讨论】:

              【解决方案13】:

              此代码将 csv 读取到 DataTable:

              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;
              }
              

              【讨论】:

              • TextFieldParser 在 Microsoft.VisualBasic.dll 中。
              【解决方案14】:

              满足简单解析需求的单一源文件解决方案,很有用。处理所有令人讨厌的边缘情况。例如新行规范化和处理带引号的字符串文字中的新行。欢迎您!

              如果您的 CSV 文件有标题,您只需从第一行读出列名(和计算列索引)。就这么简单。

              请注意,Dump 是一种 LINQPad 方法,如果您不使用 LINQPad,则可能需要删除它。

              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;
                  }
              }
              

              【讨论】:

                【解决方案15】:

                此列表中的另一个,Cinchoo ETL - 一个用于读取和写入多种文件格式(CSV、平面文件、Xml、JSON 等)的开源库

                下面的示例展示了如何快速读取 CSV 文件(不需要 POCO 对象)

                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}");
                    }
                }
                

                下面的示例展示了如何使用 POCO 对象读取 CSV 文件

                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}");
                        }
                    }
                }
                

                请查看CodeProject的文章了解如何使用它。

                【讨论】:

                  【解决方案16】:

                  基于 unlimit 在How to properly split a CSV using C# split() function? 上的帖子:

                  string[] tokens = System.Text.RegularExpressions.Regex.Split(paramString, ",");
                  

                  注意:这不处理转义/嵌套逗号等,因此仅适用于某些简单的 CSV 列表。

                  【讨论】:

                  • 这很糟糕,可能很慢:)
                  • 可能,但它可以完美且简单地用于一小组参数,因此是一个有效且有用的解决方案。为什么要否决它? “非常糟糕”有点极端,你不觉得吗?
                  • 它不处理转义/嵌套逗号等。在某些情况下可以使用,但绝对不适用于所有 csv 文件
                  • 你是对的;我将编辑回复以反映这一点。谢谢。但它仍然有它的位置。
                  • 这非常适合我正在构建 sql server clr dll 并且不能使用任何其他外部包的用例。我只需要解析一个带有文件名和行数的简单 csv 文件。
                  【解决方案17】:

                  如果有人想要一个 sn-p,他们可以直接进入他们的代码,而无需绑定库或下载包。这是我写的一个版本:

                      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;
                      }
                  

                  【讨论】:

                    猜你喜欢
                    • 2012-06-08
                    • 2018-10-10
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-12
                    • 2017-05-25
                    相关资源
                    最近更新 更多