【问题标题】:Reading CSV file and storing values into an array读取 CSV 文件并将值存储到数组中
【发布时间】:2011-03-12 14:11:15
【问题描述】:

我正在尝试读取*.csv-文件。

*.csv-文件由分号 (";") 分隔的两列组成。

我可以使用 StreamReader 读取*.csv-文件,并且可以使用Split() 函数分隔每一行。我想将每一列存储到一个单独的数组中,然后显示它。

有可能吗?

【问题讨论】:

  • @Marc:不幸的是,在非英语文化(例如意大利语)中,当您将 excel 保存到 CSV 时,它使用 ";" 作为分隔符......这使得 CSV 成为非标准 imo :(
  • 我总是将 CSV 读取为字符分隔值,因为人们将文件称为 CSV,即使他们不使用逗号作为分隔符。并且在实践中有如此多的方言具有不同的引用或转义规则,即使理论上存在 RFC,您也无法真正谈论标准。
  • CSV 文件扩展名现在应该更改为 DSV - 分隔符分隔值 文件
  • 对于所有在分隔符上简单地拆分字符串的答案,这不是最好的方法。 CSV 格式还有更多的规则,这将不包括在内。最好使用 3rd 方解析器。更多信息-dotnetcoretutorials.com/2018/08/04/csv-parsing-in-net-core

标签: c# .net arrays csv


【解决方案1】:

你可以这样做:

using System.IO;

static void Main(string[] args)
{
    using(var reader = new StreamReader(@"C:\test.csv"))
    {
        List<string> listA = new List<string>();
        List<string> listB = new List<string>();
        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            var values = line.Split(';');

            listA.Add(values[0]);
            listB.Add(values[1]);
        }
    }
}

【讨论】:

  • 谢谢你,我忘记了如何在 csv 文件中分割行(愚蠢!)但你的解决方案帮助了我 :)
  • 3 年多过去了,这个问题仍在帮助某人。我很难过你没有接受这个。
  • 不处理带逗号等的字段值
  • 应该在这里使用using 子句,或者至少手动使用Close() reader,因为它是IDisposible 资源。
  • 这也不会正确解析像column1;"Special ; char in string";column3 - tools.ietf.org/html/rfc4180这样写的CSV
【解决方案2】:

我最喜欢的 CSV 解析器是内置于 .NET 库中的。这是 Microsoft.VisualBasic 命名空间中的隐藏宝藏。 下面是一个示例代码:

using Microsoft.VisualBasic.FileIO;

var path = @"C:\Person.csv"; // Habeeb, "Dubai Media City, Dubai"
using (TextFieldParser csvParser = new TextFieldParser(path))
{
 csvParser.CommentTokens = new string[] { "#" };
 csvParser.SetDelimiters(new string[] { "," });
 csvParser.HasFieldsEnclosedInQuotes = true;

 // Skip the row with the column names
 csvParser.ReadLine();

 while (!csvParser.EndOfData)
 {
  // Read current line fields, pointer moves to the next line.
  string[] fields = csvParser.ReadFields();
  string Name = fields[0];
  string Address = fields[1];
 }
}

记得添加对Microsoft.VisualBasic的引用

关于解析器的更多细节在这里给出:http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

【讨论】:

  • 我最喜欢这个选项。我不必担心转义字符,因为该类是 CSV 解析器,而不是手动构建的东西。
  • 如果有人遇到此问题并想知道,您需要包含对 Microsoft.VisualBasic 框架程序集的引用,因为默认情况下通常不会引用它。
  • 我希望我从我的 VB6 时代就记住了这一点,多年来我会节省很多时间。虽然有些人会抱怨 VB,但如果将 dll 和命名空间添加到我的代码中,我没有问题。这有很多价值。
  • 这个解决方案是本垒打。根据我的经验,非常可靠的解析器。
  • 为什么只在VB dll中?
【解决方案3】:

LINQ方式:

var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';'));
var csv = from line in lines
          select (from piece in line
                  select piece);

^^错误 - 由尼克编辑

原来的回答者似乎试图用一个二维数组填充csv - 一个包含数组的数组。第一个数组中的每一项都包含一个表示该行号的数组,嵌套数组中的每一项都包含该特定列的数据。

var csv = from line in lines
          select (line.Split(',')).ToArray();

【讨论】:

  • @ClayShannon .NET 1.1 吗?我……很对不起你。
  • @contactmatt:我不会否认你的这种情绪。
  • 我还想指出 csv 可以被引用...所以使用 string.Split 不是一个可行的选择。
  • 我得到:'System.Array' 不包含'Split' 的定义,并且找不到接受'System.Array' 类型的第一个参数的扩展方法'Split'(你是缺少 using 指令或程序集引用?)
  • 您得到 System.Array 不包含定义,因为 lines 是一个 IEnumerable(string []) 所以 line 基本上是一个具有一个元素的字符串数组。只需将其更改为 var csv = from line in lines select (line[0].Split(',')).ToArray();
【解决方案4】:

刚发现这个库:https://github.com/JoshClose/CsvHelper

非常直观且易于使用。也有一个快速实施的 nuget 包:https://www.nuget.org/packages/CsvHelper/27.2.1。似乎也得到了我喜欢的积极维护。

将其配置为使用分号很简单:https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

【讨论】:

  • 这是最好的答案!易于使用和使用的强大库。
  • CsvHelper 库非常棒。超级快速且易于使用。
  • 如果您正在寻找一个可以处理 csv 格式的各个方面(包括带引号的字符串)的库,请使用这个库。太棒了!
  • 谢谢,非常好的库,易于使用且非常强大。
  • 性能与Microsoft.VisualBasic.FileIO.TextFieldParser 相比如何(参见@Habeeb 的回答)?
【解决方案5】:

您不能立即创建数组,因为您需要从一开始就知道行数(这需要读取 csv 文件两次)

您可以将值存储在两个List&lt;T&gt; 中,然后使用它们或使用List&lt;T&gt;.ToArray() 转换为数组

非常简单的例子:

var column1 = new List<string>();
var column2 = new List<string>();
using (var rd = new StreamReader("filename.csv"))
{
    while (!rd.EndOfStream)
    {
        var splits = rd.ReadLine().Split(';');
        column1.Add(splits[0]);
        column2.Add(splits[1]);
    }
}
// print column1
Console.WriteLine("Column 1:");
foreach (var element in column1)
    Console.WriteLine(element);

// print column2
Console.WriteLine("Column 2:");
foreach (var element in column2)
    Console.WriteLine(element);

注意

请注意,这只是一个非常简单的示例。使用 string.Split 不考虑某些记录在其中包含分隔符 ; 的情况。
如需更安全的方法,请考虑在 nuget 上使用一些特定于 csv 的库,例如 CsvHelper。

【讨论】:

  • 不考虑 ; 是值的一部分,例如 "value with ; inside it"。 CSV 将包含特殊字符的值用双引号括起来,表示它是文字字符串。
  • @ChickenFeet:当然,这就是标题的原因:“非常简单的例子”。无论如何,我可以添加一个注释;)
  • 不用担心,我注意到这里的很多其他答案也没有考虑到它:)
  • Regex.Split(sr.ReadLine(), ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]* $)"); //在 SO 上找到这个...比图书馆更快。
【解决方案6】:

我通常使用这个parser from codeproject,因为它为我处理了一堆字符转义和类似的问题。

【讨论】:

  • 这东西非常好,速度也很快。如果您处于业务环境中并且需要破解,请使用它。
  • 这个解析器在 Nuget 库中以 LumenWorks.Framework.IO 的形式提供,以防您不想注册 CodeProject 来下载它。
【解决方案7】:

这是我对最高投票答案的变体:

var contents = File.ReadAllText(filename).Split('\n');
var csv = from line in contents
          select line.Split(',').ToArray();

csv 变量随后可用于以下示例:

int headerRows = 5;
foreach (var row in csv.Skip(headerRows)
    .TakeWhile(r => r.Length > 1 && r.Last().Trim().Length > 0))
{
    String zerothColumnValue = row[0]; // leftmost column
    var firstColumnValue = row[1];
}

【讨论】:

  • 如何访问 csv 变量中的行和列?
  • 如何处理转义逗号?
  • 不处理列中的逗号。最好按照 joshb 的 answer 使用强大的库 CsvHelper
【解决方案8】:

如果您需要跳过(头)行和/或列,可以使用它来创建二维数组:

    var lines = File.ReadAllLines(path).Select(a => a.Split(';'));
    var csv = (from line in lines               
               select (from col in line
               select col).Skip(1).ToArray() // skip the first column
              ).Skip(2).ToArray(); // skip 2 headlines

如果您需要在进一步处理数据之前对其进行整形(假设前两行由标题组成,第一列是行标题 - 您不需要在数组中包含它),这将非常有用因为你只想看数据)。

注意您可以使用以下代码轻松获取标题和第一列:

    var coltitle = (from line in lines 
                    select line.Skip(1).ToArray() // skip 1st column
                   ).Skip(1).Take(1).FirstOrDefault().ToArray(); // take the 2nd row
    var rowtitle = (from line in lines select line[0] // take 1st column
                   ).Skip(2).ToArray(); // skip 2 headlines

此代码示例假定您的 *.csv 文件具有以下结构:

注意:如果您需要跳过空行 - 这有时很方便,您可以通过插入来实现

    where line.Any(a=>!string.IsNullOrWhiteSpace(a))

在上述 LINQ 代码示例中的 fromselect 语句之间。

【讨论】:

    【解决方案9】:

    您可以在 C# 中使用 Microsoft.VisualBasic.FileIO.TextFieldParser dll 以获得更好的性能

    从上面的文章中获取下面的代码示例

    static void Main()
    {
        string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv";
    
        DataTable csvData = GetDataTabletFromCSVFile(csv_file_path);
    
        Console.WriteLine("Rows count:" + csvData.Rows.Count);
    
        Console.ReadLine();
    }
    
    
    private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
    {
        DataTable csvData = new DataTable();
    
        try
        {
    
        using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
            {
                csvReader.SetDelimiters(new string[] { "," });
                csvReader.HasFieldsEnclosedInQuotes = true;
                string[] colFields = csvReader.ReadFields();
                foreach (string column in colFields)
                {
                    DataColumn datecolumn = new DataColumn(column);
                    datecolumn.AllowDBNull = true;
                    csvData.Columns.Add(datecolumn);
                }
    
                while (!csvReader.EndOfData)
                {
                    string[] fieldData = csvReader.ReadFields();
                    //Making empty value as null
                    for (int i = 0; i < fieldData.Length; i++)
                    {
                        if (fieldData[i] == "")
                        {
                            fieldData[i] = null;
                        }
                    }
                    csvData.Rows.Add(fieldData);
                }
            }
        }
        catch (Exception ex)
        {
        }
        return csvData;
    }
    

    【讨论】:

    • 它没有那么高效,因为 Split 并没有像 TextFieldParser 那样做所有事情。例如,跳过注释行、处理带引号的字段以及删除开头/结尾的空格。不完全是 1:1 的比较。
    【解决方案10】:

    大家好,我为此创建了一个静态类。 + 列检查 + 配额符号移除

    public static class CSV
    {
        public static List<string[]> Import(string file, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
        {
            return ReadCSVFile(file, csvDelimiter, ignoreHeadline, removeQuoteSign);
        }
    
        private static List<string[]> ReadCSVFile(string filename, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
        {
            string[] result = new string[0];
            List<string[]> lst = new List<string[]>();
    
            string line;
            int currentLineNumner = 0;
            int columnCount = 0;
    
            // Read the file and display it line by line.  
            using (System.IO.StreamReader file = new System.IO.StreamReader(filename))
            {
                while ((line = file.ReadLine()) != null)
                {
                    currentLineNumner++;
                    string[] strAr = line.Split(csvDelimiter);
                    // save column count of dirst line
                    if (currentLineNumner == 1)
                    {
                        columnCount = strAr.Count();
                    }
                    else
                    {
                        //Check column count of every other lines
                        if (strAr.Count() != columnCount)
                        {
                            throw new Exception(string.Format("CSV Import Exception: Wrong column count in line {0}", currentLineNumner));
                        }
                    }
    
                    if (removeQuoteSign) strAr = RemoveQouteSign(strAr);
    
                    if (ignoreHeadline)
                    {
                        if(currentLineNumner !=1) lst.Add(strAr);
                    }
                    else
                    {
                        lst.Add(strAr);
                    }
                }
    
            }
    
            return lst;
        }
        private static string[] RemoveQouteSign(string[] ar)
        {
            for (int i = 0;i< ar.Count() ; i++)
            {
                if (ar[i].StartsWith("\"") || ar[i].StartsWith("'")) ar[i] = ar[i].Substring(1);
                if (ar[i].EndsWith("\"") || ar[i].EndsWith("'")) ar[i] = ar[i].Substring(0,ar[i].Length-1);
    
            }
            return ar;
        }
    
    }
    

    【讨论】:

      【解决方案11】:

      我花了几个小时寻找合适的库,但最后我编写了自己的代码 :) 您可以使用所需的任何工具读取文件(或数据库),然后将以下例程应用于每一行:

      private static string[] SmartSplit(string line, char separator = ',')
      {
          var inQuotes = false;
          var token = "";
          var lines = new List<string>();
          for (var i = 0; i < line.Length; i++) {
              var ch = line[i];
              if (inQuotes) // process string in quotes, 
              {
                  if (ch == '"') {
                      if (i<line.Length-1 && line[i + 1] == '"') {
                          i++;
                          token += '"';
                      }
                      else inQuotes = false;
                  } else token += ch;
              } else {
                  if (ch == '"') inQuotes = true;
                  else if (ch == separator) {
                      lines.Add(token);
                      token = "";
                      } else token += ch;
                  }
          }
          lines.Add(token);
          return lines.ToArray();
      }
      

      【讨论】:

        【解决方案12】:
        var firstColumn = new List<string>();
        var lastColumn = new List<string>();
        
        // your code for reading CSV file
        
        foreach(var line in file)
        {
            var array = line.Split(';');
            firstColumn.Add(array[0]);
            lastColumn.Add(array[1]);
        }
        
        var firstArray = firstColumn.ToArray();
        var lastArray = lastColumn.ToArray();
        

        【讨论】:

        • 感谢您的帮助。它可能有助于解决我的问题。实际上我必须从文件中读取数据,然后插入数据库。在插入时,我收到主键约束错误(因为我已经在数据库中有数据)。所以,我需要编程使得变量已经存在,然后更新数据。
        • 如果是 PK,我假设第一个值 - 您需要通过 id 从数据库中获取记录,如果存在则发出 UPDATE 语句,否则插入新记录。
        【解决方案13】:

        这是一种特殊情况,其中一个数据字段将分号 (";") 作为其数据的一部分,在这种情况下,上述大多数答案都会失败。

        这种情况下的解决方案是

        string[] csvRows = System.IO.File.ReadAllLines(FullyQaulifiedFileName);
        string[] fields = null;
        List<string> lstFields;
        string field;
        bool quoteStarted = false;
        foreach (string csvRow in csvRows)
        {
            lstFields = new List<string>();
            field = "";
            for (int i = 0; i < csvRow.Length; i++)
            {
                string tmp = csvRow.ElementAt(i).ToString();
                if(String.Compare(tmp,"\"")==0)
                {
                    quoteStarted = !quoteStarted;
                }
                if (String.Compare(tmp, ";") == 0 && !quoteStarted)
                {
                    lstFields.Add(field);
                    field = "";
                }
                else if (String.Compare(tmp, "\"") != 0)
                {
                    field += tmp;
                }
            }
            if(!string.IsNullOrEmpty(field))
            {
                lstFields.Add(field);
                field = "";
            }
        // This will hold values for each column for current row under processing
            fields = lstFields.ToArray(); 
        }
        

        【讨论】:

          【解决方案14】:

          开源Angara.Table 库允许将 CSV 加载到类型化列中,因此您可以从列中获取数组。每列都可以按名称或索引进行索引。见http://predictionmachines.github.io/Angara.Table/saveload.html

          该库遵循 CSV 的 RFC4180;它支持类型推断和多行字符串。

          例子:

          using System.Collections.Immutable;
          using Angara.Data;
          using Angara.Data.DelimitedFile;
          
          ...
          
          ReadSettings settings = new ReadSettings(Delimiter.Semicolon, false, true, null, null);
          Table table = Table.Load("data.csv", settings);
          ImmutableArray<double> a = table["double-column-name"].Rows.AsReal;
          
          for(int i = 0; i < a.Length; i++)
          {
              Console.WriteLine("{0}: {1}", i, a[i]);
          }
          

          您可以使用类型 Column 来查看列类型,例如

          Column c = table["double-column-name"];
          Console.WriteLine("Column {0} is double: {1}", c.Name, c.Rows.IsRealColumn);
          

          由于该库专注于 F#,您可能需要添加对 FSharp.Core 4.4 程序集的引用;单击项目上的“添加引用”,然后在“程序集”->“扩展”下选择 FSharp.Core 4.4。

          【讨论】:

            【解决方案15】:

            我多年来一直在使用 csvreader.com(付费组件),从来没有遇到过问题。它坚固、小巧、快速,但您必须为此付费。您可以将分隔符设置为您喜欢的任何内容。

            using (CsvReader reader = new CsvReader(s) {
                reader.Settings.Delimiter = ';';
                reader.ReadHeaders();  // if headers on a line by themselves.  Makes reader.Headers[] available
                while (reader.ReadRecord())
                    ... use reader.Values[col_i] ...
            }
            

            【讨论】:

              【解决方案16】:

              我只是正在写硕士论文的学生,但这是我解决它的方法,它对我很有效。首先从目录中选择文件(仅 csv 格式),然后将数据放入列表中。

              List<float> t = new List<float>();
              List<float> SensorI = new List<float>();
              List<float> SensorII = new List<float>();
              List<float> SensorIII = new List<float>();
              using (OpenFileDialog dialog = new OpenFileDialog())
              {
                  try
                  {
                      dialog.Filter = "csv files (*.csv)|*.csv";
                      dialog.Multiselect = false;
                      dialog.InitialDirectory = ".";
                      dialog.Title = "Select file (only in csv format)";
                      if (dialog.ShowDialog() == DialogResult.OK)
                      {
                          var fs = File.ReadAllLines(dialog.FileName).Select(a => a.Split(';'));
                          int counter = 0;
                          foreach (var line in fs)
                          {
                              counter++;
                              if (counter > 2)    // Skip first two headder lines
                              {
                                  this.t.Add(float.Parse(line[0]));
                                  this.SensorI.Add(float.Parse(line[1]));
                                  this.SensorII.Add(float.Parse(line[2]));
                                  this.SensorIII.Add(float.Parse(line[3]));
                              }
                          }
                      }
                  }
                  catch (Exception exc)
                  {
                      MessageBox.Show(
                          "Error while opening the file.\n" + exc.Message, 
                          this.Text, 
                          MessageBoxButtons.OK, 
                          MessageBoxIcon.Error
                      );
                  }
              }
              

              【讨论】:

                【解决方案17】:

                这是我的 2 个简单的静态方法,用于将文本从 csv 文件转换为 List&lt;List&lt;string&gt;&gt;,反之亦然。每种方法都使用行转换器。

                此代码应考虑到 csv 文件的所有可能性。您可以定义自己的 csv 分隔符,此方法尝试纠正 escape double 'quote' char,并处理引号中的所有文本都是一个单元格且 csv 分隔符在带引号的字符串内,包括一个单元格中的多行,并且可以忽略空行

                最后一种方法仅用于测试。所以你可以忽略它,或者用这个测试方法测试你自己的或其他解决方案:)。为了测试,我使用了这个 4 行 2 行的硬 csv:

                0,a,""bc,d
                "e, f",g,"this,is, o
                ne ""lo
                ng, cell""",h
                

                这是最终代码。为简单起见,我删除了所有 try catch 块。

                using System;
                using System.Collections.Generic;
                using System.Linq;
                
                public static class Csv {
                  public static string FromListToString(List<List<string>> csv, string separator = ",", char quotation = '"', bool returnFirstRow = true)
                  {
                    string content = "";
                    for (int row = 0; row < csv.Count; row++) {
                      content += (row > 0 ? Environment.NewLine : "") + RowFromListToString(csv[row], separator, quotation);
                    }
                    return content;
                  }
                
                  public static List<List<string>> FromStringToList(string content, string separator = ",", char quotation = '"', bool returnFirstRow = true, bool ignoreEmptyRows = true)
                  {
                    List<List<string>> csv = new List<List<string>>();
                    string[] rows = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                    if (rows.Length <= (returnFirstRow ? 0 : 1)) { return csv; }
                    List<string> csvRow = null;
                    for (int rowIndex = 0; rowIndex < rows.Length; rowIndex++) {
                      (List<string> row, bool rowClosed) = RowFromStringToList(rows[rowIndex], csvRow, separator, quotation);
                      if (rowClosed) { if (!ignoreEmptyRows || row.Any(rowItem => rowItem.Length > 0)) { csv.Add(row); csvRow = null; } } // row ok, add to list
                      else { csvRow = row; } // not fully created, continue
                    }
                    if (!returnFirstRow) { csv.RemoveAt(0); } // remove header
                    return csv;
                  }
                
                  public static string RowFromListToString(List<string> csvData, string separator = ",", char quotation = '"')
                  {
                    csvData = csvData.Select(element =>
                    {
                      if (element.Contains(quotation)) {
                        element = element.Replace(quotation.ToString(), quotation.ToString() + quotation.ToString());
                      }
                      if (element.Contains(separator) || element.Contains(Environment.NewLine)) {
                        element = "\"" + element + "\"";
                      }
                      return element;
                    }).ToList();
                    return string.Join(separator, csvData);
                  }
                
                  public static (List<string>, bool) RowFromStringToList(string csvRow, List<string> continueWithRow = null, string separator = ",", char quotation = '"')
                  {
                    bool rowClosed = true;
                    if (continueWithRow != null && continueWithRow.Count > 0) {
                      // in previous result quotation are fixed so i need convert back to double quotation
                      string previousCell = quotation.ToString() + continueWithRow.Last().Replace(quotation.ToString(), quotation.ToString() + quotation.ToString()) + Environment.NewLine;
                      continueWithRow.RemoveAt(continueWithRow.Count - 1);
                      csvRow = previousCell + csvRow;
                    }
                
                    char tempQuote = (char)162;
                    while (csvRow.Contains(tempQuote)) { tempQuote = (char)(tempQuote + 1); }
                    char tempSeparator = (char)(tempQuote + 1);
                    while (csvRow.Contains(tempSeparator)) { tempSeparator = (char)(tempSeparator + 1); }
                
                    csvRow = csvRow.Replace(quotation.ToString() + quotation.ToString(), tempQuote.ToString());
                    if(csvRow.Split(new char[] { quotation }, StringSplitOptions.None).Length % 2 == 0) { rowClosed = !rowClosed; }
                    string[] csvSplit = csvRow.Split(new string[] { separator }, StringSplitOptions.None);
                
                    List<string> csvList = csvSplit
                      .ToList()
                      .Aggregate("",
                          (string row, string item) => {
                              if (row.Count((ch) => ch == quotation) % 2 == 0) { return row + (row.Length > 0 ? tempSeparator.ToString() : "") + item; }
                              else { return row + separator + item; }
                          },
                          (string row) => row.Split(tempSeparator).Select((string item) => item.Trim(quotation).Replace(tempQuote, quotation))
                      ).ToList();
                    if (continueWithRow != null && continueWithRow.Count > 0) {
                      return (continueWithRow.Concat(csvList).ToList(), rowClosed);
                    }
                    return (csvList, rowClosed);
                  }
                
                  public static bool Test()
                  {
                    string csvText = "0,a,\"\"bc,d" + Environment.NewLine + "\"e, f\",g,\"this,is, o" + Environment.NewLine + "ne \"\"lo" + Environment.NewLine + "ng, cell\"\"\",h";
                    List<List<string>> csvList = new List<List<string>>() { new List<string>() { "0", "a", "\"bc", "d" }, new List<string>() { "e, f", "g", "this,is, o" + Environment.NewLine + "ne \"lo" + Environment.NewLine + "ng, cell\"", "h" } };
                
                    List<List<string>> csvTextAsList = Csv.FromStringToList(csvText);
                    bool ok = Enumerable.SequenceEqual(csvList[0], csvTextAsList[0]) && Enumerable.SequenceEqual(csvList[1], csvTextAsList[1]);
                    string csvListAsText = Csv.FromListToString(csvList);
                    return ok && csvListAsText == csvText;
                  }
                }
                

                使用示例

                // get List<List<string>> representation of csv
                var csvFromText = Csv.FromStringToList(csvAsText);
                
                // read csv file with custom separator and quote
                // return no header and ignore empty rows
                var csvFile = File.ReadAllText(csvFileFullPath);
                var csvFromFile = Csv.FromStringToList(csvFile, ";", '"', false, false);
                
                // get text representation of csvData from List<List<string>>
                var csvAsText = Csv.FromListToString(csvData);
                

                注意事项:
                这:char tempQuote = (char)162; 是 ASCI 表中的第一个稀有字符。脚本会搜索此字符,或前几个不在文本中的 ascii 字符,并将其用作临时转义字符和引号字符。

                【讨论】:

                  【解决方案18】:

                  还是错了。您需要补偿引号中的“”。 这是我的解决方案 Microsoft 风格的 csv。

                                 /// <summary>
                      /// Microsoft style csv file.  " is the quote character, "" is an escaped quote.
                      /// </summary>
                      /// <param name="fileName"></param>
                      /// <param name="sepChar"></param>
                      /// <param name="quoteChar"></param>
                      /// <param name="escChar"></param>
                      /// <returns></returns>
                      public static List<string[]> ReadCSVFileMSStyle(string fileName, char sepChar = ',', char quoteChar = '"')
                      {
                          List<string[]> ret = new List<string[]>();
                  
                          string[] csvRows = System.IO.File.ReadAllLines(fileName);
                  
                          foreach (string csvRow in csvRows)
                          {
                              bool inQuotes = false;
                              List<string> fields = new List<string>();
                              string field = "";
                              for (int i = 0; i < csvRow.Length; i++)
                              {
                                  if (inQuotes)
                                  {
                                      // Is it a "" inside quoted area? (escaped litteral quote)
                                      if(i < csvRow.Length - 1 && csvRow[i] == quoteChar && csvRow[i+1] == quoteChar)
                                      {
                                          i++;
                                          field += quoteChar;
                                      }
                                      else if(csvRow[i] == quoteChar)
                                      {
                                          inQuotes = false;
                                      }
                                      else
                                      {
                                          field += csvRow[i];
                                      }
                                  }
                                  else // Not in quoted region
                                  {
                                       if (csvRow[i] == quoteChar)
                                      {
                                          inQuotes = true;
                                      }
                                      if (csvRow[i] == sepChar)
                                      {
                                          fields.Add(field);
                                          field = "";
                                      }
                                      else 
                                      {
                                          field += csvRow[i];
                                      }
                                  }
                              }
                              if (!string.IsNullOrEmpty(field))
                              {
                                  fields.Add(field);
                                  field = "";
                              }
                              ret.Add(fields.ToArray());
                          }
                  
                          return ret;
                      }
                  }
                  

                  【讨论】:

                  • 它不处理列值中有换行符的情况;)
                  【解决方案19】:

                  我有一个完全符合您需要的库。

                  前段时间,我为处理 CSV 文件编写了简单且足够快的库。您可以通过以下链接找到它:https://github.com/ukushu/DataExporter/blob/master/Csv.cs

                  它适用于 CSV,就像二维数组一样。完全符合您的需要。

                  例如,如果您需要第三行的所有值,您只需编写:

                  Csv csv = new Csv();
                  
                  csv.FileOpen("c:\\file1.csv");
                  
                  var allValuesOf3rdRow = csv.Rows[2];
                  

                  或读取第三行的第二个单元格:

                  var value = csv.Rows[2][1];
                  

                  【讨论】:

                    【解决方案20】:

                    look at this

                    使用 CsvFramework;

                    使用 System.Collections.Generic;

                    命名空间 CvsParser {

                    public class Customer
                    {
                        public int Id { get; set; }
                        public string Name { get; set; }
                        public List<Order> Orders { get; set; }        
                    }
                    
                    public class Order
                    {
                        public int Id { get; set; }
                    
                        public int CustomerId { get; set; }
                        public int Quantity { get; set; }
                    
                        public int Amount { get; set; }
                    
                        public List<OrderItem> OrderItems { get; set; }
                    
                    }
                    
                    public class Address
                    {
                        public int Id { get; set; }
                        public int CustomerId { get; set; }
                    
                        public string Name { get; set; }
                    }
                    
                    public class OrderItem
                    {
                        public int Id { get; set; }
                        public int OrderId { get; set; }
                    
                        public string ProductName { get; set; }
                    }
                    
                    class Program
                    {
                        static void Main(string[] args)
                        {
                    
                            var customerLines = System.IO.File.ReadAllLines(@"Customers.csv");
                            var orderLines = System.IO.File.ReadAllLines(@"Orders.csv");
                            var orderItemLines = System.IO.File.ReadAllLines(@"OrderItemLines.csv");
                    
                            CsvFactory.Register<Customer>(builder =>
                            {
                                builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
                                builder.Add(a => a.Name).Type(typeof(string)).Index(1);
                                builder.AddNavigation(n => n.Orders).RelationKey<Order, int>(k => k.CustomerId);
                    
                            }, false, ',', customerLines);
                    
                            CsvFactory.Register<Order>(builder =>
                            {
                                builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
                                builder.Add(a => a.CustomerId).Type(typeof(int)).Index(1);
                                builder.Add(a => a.Quantity).Type(typeof(int)).Index(2);
                                builder.Add(a => a.Amount).Type(typeof(int)).Index(3);
                                builder.AddNavigation(n => n.OrderItems).RelationKey<OrderItem, int>(k => k.OrderId);
                    
                            }, true, ',', orderLines);
                    
                    
                            CsvFactory.Register<OrderItem>(builder =>
                            {
                                builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
                                builder.Add(a => a.OrderId).Type(typeof(int)).Index(1);
                                builder.Add(a => a.ProductName).Type(typeof(string)).Index(2);
                    
                    
                            }, false, ',', orderItemLines);
                    
                    
                    
                            var customers = CsvFactory.Parse<Customer>();
                    
                    
                        }
                    }
                    

                    }

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-03-17
                      • 2015-01-22
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多