读取CSV文件并将值存储到数组中

Rus*_*hah 295 .net c# csv arrays

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

所述*.csv-file包括由分号分隔的两列的(" ; ").

我能够*.csv使用StreamReader 读取-file,并能够使用该Split()函数分隔每一行.我想将每列存储到一个单独的数组中然后显示它.

有可能吗?

Mic*_* M. 377

你可以这样做:

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]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这也不能正确地解析像`column1;"Special; char in string"; column3` - https://tools.ietf.org/html/rfc4180 (27认同)
  • 不使用逗号等处理字段值. (12认同)
  • 应该在这里使用`using`子句,或者至少手动`Close()``reader`,因为它是`IDisposible`资源. (12认同)
  • 谢谢你,我忘记了如何在csv文件中分割线条(愚蠢的我!)但你的解决方案帮助了我:) (5认同)
  • 三年多了,这个问题仍然在帮助别人。我很遗憾您没有对此接受。 (3认同)
  • .EndOfStream 在 .NET 1.1 中不可用。while (reader.WriteLine) 是要走的路吗? (2认同)
  • @ClayShannon `EndOfStream` 的实现或多或少会检查读取器的当前位置是否小于文件中总字节数的长度。这适用于我的 while 构造函数`rdr.BaseStream.Position &lt; rdr.BaseStream.Length`。请记住,“StreamReader”只是“Stream”的方便包装器,因此如果您的 .NET 版本没有自定义方法,您可以实现自己的自定义方法。 (2认同)
  • 通过编写自己的文档来处理csv解析中的所有极端情况都是有风险的。最好使用为此制造的包装。我喜欢下面的[this answer](http://stackoverflow.com/a/16193999/375688)中的一个。 (2认同)

Hab*_*eeb 155

我最喜欢的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];
 }
}
Run Code Online (Sandbox Code Playgroud)

请记住添加引用 Microsoft.VisualBasic

有关解析器的更多详细信息,请参见:http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

  • 如果有人碰到这个并且想知道,你需要包含对`Microsoft.VisualBasic`框架程序集的引用,因为默认情况下通常不会引用它. (22认同)
  • 我最喜欢这个选项.我不必担心转义字符,因为该类是CSV解析器而不是手动构建的东西. (5认同)
  • 为什么只能在VB dll 中? (4认同)
  • 该解决方案比其他解决方案要好得多,因为它允许字段为逗号和换行符提供显式值 (3认同)
  • 我希望我在VB6的日子里记住这一点,多年来我会节省很多时间.虽然有些人会喋喋不休地谈论VB,但如果它有价值,我就没有问题将dll和命名空间添加到我的代码中.这有很多价值. (2认同)
  • 这个解决方案是一个本垒打。根据我的经验,非常可靠的解析器。 (2认同)

as-*_*cii 73

LINQ方式:

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

^^错了 - 尼克编辑

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

var csv = from line in lines
          select (line.Split(',')).ToArray();
Run Code Online (Sandbox Code Playgroud)

  • @ClayShannon .NET 1.1?我...非常抱歉. (13认同)
  • 我还想指出csv可以引用...所以使用string.Split不是一个可行的选择. (9认同)
  • @contactmatt:我不会贬低你的那种情绪. (5认同)
  • 我得到:'System.Array'不包含'Split'的定义,并且没有扩展方法'Split'接受类型'System.Array'的第一个参数可以找到(你是否缺少using指令或程序集引用?) (4认同)
  • 也许我错过了一些东西,但我不确定你的csv变量的意思是什么 - 你不是只是重新创建了相同的数据结构吗? (2认同)
  • 您正在获取System.Array不包含定义,因为lines是IEnumerable(string []),因此line本质上是具有一个元素的字符串数组。只需将其更改为var csv =从行中选择(line [0] .Split(','))。ToArray(); (2认同)

Pau*_*aul 33

我通常使用codeproject中的这个解析器,因为它有一堆字符转义和它为我处理的类似.

  • 此解析器在Nuget库中可用作LumenWorks.Framework.IO,以防您不想注册CodeProject进行下载. (7认同)
  • 这件事非常好,也很快.如果您处于业务状况并需要破解,请使用此功能. (2认同)

dig*_*All 31

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

您可以将值存储为两个List<T>,然后使用它们或使用转换为数组List<T>.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);
Run Code Online (Sandbox Code Playgroud)

NB

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

  • @ChickenFeet:当然,这就是标题的原因:*“非常简单的例子”*。无论如何,我可以添加一个注释;) (2认同)
  • Regex.Split(sr.ReadLine(), ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); //找到这太……比图书馆快了。 (2认同)

jos*_*shb 31

刚刚遇到这个库:https://github.com/JoshClose/CsvHelper

非常直观且易于使用.还有一个nuget包,可以快速实现:http://nuget.org/packages/CsvHelper/1.17.0 .也似乎积极维护我喜欢.

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

  • 这是最好的答案!强大的库,易于插入和滚动. (3认同)
  • CsvHelper库太棒了.超快速且易于使用. (3认同)
  • 如果您正在寻找一个可以处理csv格式的各个方面的库,包括带引号的字符串,请使用此库.真棒! (3认同)
  • 与“ Microsoft.VisualBasic.FileIO.TextFieldParser”相比,性能如何(参见@Habeeb的答案)? (2认同)

tom*_*msv 30

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

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

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];
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*att 11

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

    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
Run Code Online (Sandbox Code Playgroud)

如果您需要在进一步处理数据之前对数据进行整形(假设前两行由标题组成,第一列是行标题 - 您不需要在数组中,因为您只是想要看数据).

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

    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
Run Code Online (Sandbox Code Playgroud)

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

CSV矩阵

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

    where line.Any(a=>!string.IsNullOrWhiteSpace(a))
Run Code Online (Sandbox Code Playgroud)

在上面的LINQ代码示例中fromselect语句和语句之间.


kom*_*bsh 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 它没有那么高效,因为Split不会完成TextFieldParser所做的一切.例如,跳过注释行,处理引用的字段,并删除开始/尾随空格.不完全是1:1的比较. (9认同)
  • 它的效率不高,如http://www.dotnetperls.com/textfieldparser所述 (4认同)

Jak*_*cki 5

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();
Run Code Online (Sandbox Code Playgroud)


小智 5

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

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

}
Run Code Online (Sandbox Code Playgroud)


Zby*_*ski 5

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

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();
}
Run Code Online (Sandbox Code Playgroud)