我正在读取*.csv文件。

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

我能够阅读*.csv文件使用StreamReader,并能够通过使用Split()函数分离每一行。我想将每一列存储到一个单独的数组中,然后显示它。

有可能做到吗?


当前回答

以下是我对投票最多的答案的修改:

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

其他回答

这是我的2个简单的静态方法,将文本从csv文件转换为列表<列表<字符串>>,反之亦然。每种方法都使用行转换器。

这段代码应该考虑csv文件的所有可能性。您可以定义自己的csv分隔符,该方法尝试纠正转义双引号字符,并处理当所有文本在引号中是一个单元格,csv分隔符在引号字符串中,包括一个单元格中的多行,可以忽略空行。

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

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字符,并将其用作临时转义和引用字符。

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

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

我最喜欢的CSV解析器是内置于. net库中的。这是微软内部隐藏的宝藏。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];
 }
}

记得添加对微软的引用。VisualBasic

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

在下面的代码中,需要在csv中进行json转换

您可以不做任何更改就使用下面的代码。

这段代码将使用两个行标题或一个行标题。

下面的代码读取上传的IForm文件并转换为内存流。

如果你想使用文件路径而不是上传文件,你可以替换

new StreamReader(ms, System.Text.Encoding)UTF8, true))与新的StreamReader("../../examplefilepath");

using (var ms = new MemoryStream())
{
    administrativesViewModel.csvFile.CopyTo(ms);
    ms.Position = 0;
    using (StreamReader csvReader = new StreamReader(ms, System.Text.Encoding.UTF8, true))
    {
        List<string> lines = new List<string>();
        while (!csvReader.EndOfStream)
        {
            var line = csvReader.ReadLine();
            var values = line.Split(';');
            if (values[0] != "" && values[0] != null)
            {
                lines.Add(values[0]);
            }
        }
        var csv = new List<string[]>();
        foreach (string item in lines)
        {
            csv.Add(item.Split(','));
        }
        var properties = lines[0].Split(',');
        int csvI = 1;
        var listObjResult = new List<Dictionary<string, string>>();
        if (lines.Count() > 1)
        {
            var ln = lines[0].Substring(0, lines[0].Count() - 1);
            var ln1 = lines[1].Substring(0, lines[1].Count() - 1);
            var lnSplit = ln.Split(',');
            var ln1Split = ln1.Split(',');
            if (lnSplit.Count() != ln1Split.Count())
            {
                properties = lines[1].Split(',');
                csvI = 2;
            }
        }
        for (int i = csvI; i < csv.Count(); i++)
        {
            var objResult = new Dictionary<string, string>();
            if (csvI > 0)
            {
                var splitProp = lines[0].Split(":");
                if (splitProp.Count() > 1)
                {
                    if (splitProp[0] != "" && splitProp[0] != null && splitProp[1] != "" && splitProp[1] != null)
                    {
                        objResult.Add(splitProp[0], splitProp[1]);
                    }
                }
            }
            for (int j = 0; j < properties.Length; j++)
                if (!properties[j].Contains(":"))
                {
                    objResult.Add(properties[j], csv[i][j]);
                }
            listObjResult.Add(objResult);
        }
        var result = JsonConvert.SerializeObject(listObjResult);
        var result2 = JArray.Parse(result);
        Console.WriteLine(result2);
    }
}