【问题标题】:Very simple C# CSV reader非常简单的 C# CSV 阅读器
【发布时间】:2009-09-03 19:23:37
【问题描述】:

我想从 CSV 文件创建一个数组。

这和你想象的一样简单,CSV 文件永远只有一行和这些值:

Device, SignalStrength, Location, Time, Age.

我想将这些值放入一维数组中。

我尝试了一些示例,但它们都比要求的复杂。

【问题讨论】:

  • 有点家庭作业的味道 - 向我们展示你目前拥有的东西
  • “成一维数组”听起来很奇怪,您确定要释放换行信息吗?
  • @HenkHolterman OP 声明永远只有一行
  • @KingCronus 我们在 2012 年,这个问题有一个公认的答案,何必呢?
  • @AdrianIftode,我注意到了这个问题,因为新答案(底部)将其放入 c# 活动列表中。我没有疏通这个,他们做到了。

标签: c# csv


【解决方案1】:

你可以试试下面的 LINQ sn-p。

string[] allLines = File.ReadAllLines(@"E:\Temp\data.csv");

    var query = from line in allLines
                let data = line.Split(',')
                select new
                {
                    Device = data[0],
                    SignalStrength = data[1],
                    Location = data[2], 
                    Time = data[3],
                    Age = Convert.ToInt16(data[4])
                };

更新:经过一段时间,事情发生了变化。截至目前,我更喜欢使用这个库http://www.aspnetperformance.com/post/LINQ-to-CSV-library.aspx

【讨论】:

  • 嗨 Ramesh.. 你的解决方案很棒.. 但是你如何逃避逗号??
  • @andrew007 - 我想到的第一件事是使用正则表达式进行拆分。查看regexadvice.com/blogs/wayneking/archive/2004/01/12/271.aspx
  • @ramesh “有些人在遇到问题时会想‘我知道,我会使用正则表达式。’现在他们有两个问题。” - 杰米扎温斯基。看看secretgeek.net/csv_trouble.asp
  • LINQ-to-CSV 绝对是要走的路。如此简单易用!
【解决方案2】:

如果只有一行,则执行以下操作:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        String[] values = File.ReadAllText(@"d:\test.csv").Split(',');
    }
}

【讨论】:

  • 不不不,这太复杂了!!
  • 如果任何字段包含逗号,这将失败。
  • 如何处理新行?
  • @jamesdeath123 CSV 列值可以包含逗号,只要它们用双引号括起来,例如“这是一个测试”。
  • 这个答案是错误的,不应该是公认的答案,因为除了最基本的 csv 文件之外它不会处理任何东西,并且大多数可以创建 CSV 的系统将能够创建此解决方案会失败的文件载入。其中包括我正在寻找解决方案的文件类型。
【解决方案3】:

这是我制作的一个简单函数。它接受一个字符串 CSV 行并返回一个字段数组:

它适用于 Excel 生成的 CSV 文件以及许多其他变体。

    public static string[] ParseCsvRow(string r)
    {

        string[] c;
        string t;
        List<string> resp = new List<string>();
        bool cont = false;
        string cs = "";

        c = r.Split(new char[] { ',' }, StringSplitOptions.None);

        foreach (string y in c)
        {
            string x = y;


            if (cont)
            {
                // End of field
                if (x.EndsWith("\""))
                {
                    cs += "," + x.Substring(0, x.Length - 1);
                    resp.Add(cs);
                    cs = "";
                    cont = false;
                    continue;

                }
                else
                {
                    // Field still not ended
                    cs += "," + x;
                    continue;
                }
            }

            // Fully encapsulated with no comma within
            if (x.StartsWith("\"") && x.EndsWith("\""))
            {
                if ((x.EndsWith("\"\"") && !x.EndsWith("\"\"\"")) && x != "\"\"")
                {
                    cont = true;
                    cs = x;
                    continue;
                }

                resp.Add(x.Substring(1, x.Length - 2));
                continue;
            }

            // Start of encapsulation but comma has split it into at least next field
            if (x.StartsWith("\"") && !x.EndsWith("\""))
            {
                cont = true;
                cs += x.Substring(1);
                continue;
            }

            // Non encapsulated complete field
            resp.Add(x);

        }

        return resp.ToArray();

    }

【讨论】:

  • 当你有 cell1, "cell2", ",,,,,,,,", "previous failed" 时这会失败
【解决方案4】:

上面这个固定版本的代码记住了 CVS 行的最后一个元素 ;-)

(使用包含 5400 行和 26 个元素的 CSV 文件进行测试)

   public static string[] CSVRowToStringArray(string r, char fieldSep = ',', char stringSep = '\"')  {
            bool bolQuote = false;
            StringBuilder bld = new StringBuilder();
            List<string> retAry = new List<string>();

            foreach (char c in r.ToCharArray())
                if ((c == fieldSep && !bolQuote))
                {
                    retAry.Add(bld.ToString());
                    bld.Clear();
                }
                else
                    if (c == stringSep)
                        bolQuote = !bolQuote;
                    else
                        bld.Append(c);

            /* to solve the last element problem */
            retAry.Add(bld.ToString()); /* added this line */
            return retAry.ToArray();
        }

【讨论】:

    【解决方案5】:

    这是我在一个项目中使用的,解析单行数据。

        private string[] csvParser(string csv, char separator = ',')
        {
            List <string> = new <string>();
            string[] temp = csv.Split(separator);
            int counter = 0;
            string data = string.Empty;
            while (counter < temp.Length)
            {
                data = temp[counter].Trim();
                if (data.Trim().StartsWith("\""))
                {
                    bool isLast = false;
                    while (!isLast && counter < temp.Length)
                    {
                        data += separator.ToString() + temp[counter + 1];
                        counter++;
                        isLast = (temp[counter].Trim().EndsWith("\""));
                    }
                }
                parsed.Add(data);
                counter++;
            }
    
            return parsed.ToArray();
    
        }
    

    http://zamirsblog.blogspot.com/2013/09/c-csv-parser-csvparser.html

    【讨论】:

    • 我认为第 3 行应该是: List parsed = new List();
    • 不错的尝试,但不幸的是失败,行数据上出现“超出数组边界”异常 += separator.ToString() + temp[counter + 1];在格式良好的线上:(
    【解决方案6】:

    我的解决方案处理引号、覆盖字段和字符串分隔符等。它又短又甜。

        public static string[] CSVRowToStringArray(string r, char fieldSep = ',', char stringSep = '\"')
        {
            bool bolQuote = false;
            StringBuilder bld = new StringBuilder();
            List<string> retAry = new List<string>();
    
            foreach (char c in r.ToCharArray())
                if ((c == fieldSep && !bolQuote))
                {
                    retAry.Add(bld.ToString());
                    bld.Clear();
                }
                else
                    if (c == stringSep)
                        bolQuote = !bolQuote;
                    else
                        bld.Append(c);
    
            return retAry.ToArray();
        }
    

    【讨论】:

    • 这个解决方案似乎丢失了最后一个值,即使在没有引号的非常简单的测试中也是如此
    【解决方案7】:

    首先需要了解什么是CSV以及如何编写。

    (大多数答案(目前所有答案)都没有使用此要求,这就是为什么它们都是错误的!)

    1. 每个下一个字符串 (/r/n) 都是下一个“表格”行。
    2. “表格”单元格由一些分隔符分隔。
    3. 可以使用任何符号作为分隔符。通常是\t,
    4. 每个单元格都可能在单元格内包含此分隔符(在这种情况下,单元格必须以双引号符号开头并在末尾有双引号)
    5. 每个单元格可能都可以在单元格内包含/r/n 符号(在这种情况下,单元格必须以双引号符号开头并在末尾有双引号)

    前段时间,我基于标准Microsoft.VisualBasic.FileIO 库为CSV 读/写编写了简单的类。使用这个简单的类,您将能够像使用二维数组一样使用 CSV。

    使用我的库的简单示例:

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

    您可以通过以下链接找到我的课程并研究其编写方式: https://github.com/ukushu/DataExporter

    这个库代码运行速度非常快,源代码非常短。

    PS:同时这个解决方案对统一不起作用。

    PS2:另一种解决方案是使用库“LINQ-to-CSV”。它也必须运作良好。但它会更大。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-18
      • 2012-09-30
      • 1970-01-01
      相关资源
      最近更新 更多