web-dev-qa-db-ja.com

非常にシンプルなC#CSVリーダー

CSVファイルから配列を作成したいと思います。

これは想像できるほど簡単です。CSVファイルには1行と次の値しかありません。

Device, SignalStrength, Location, Time, Age.

これらの値を1次元配列に入れたいです。

私はいくつかの例を試しましたが、それらはすべて必要以上に複雑です。

37
DNN

行が1行しかない場合は、次のようにします。

using System;
using System.IO;

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

以下のLINQスニペットのようなものを試すことができます。

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

UPDATE:一定の期間、状況は進化しました。今のところ、私はこのライブラリを使用したいと思います http://www.aspnetperformance.com/post/LINQ-to-CSV-library.aspx

64
Ramesh

これが私が作った簡単な関数です。文字列の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();

    }
8
Chris Wilson

上記のコードの修正バージョンは、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();
        }
4
Paolo D.a

これは私がプロジェクトで使用したもので、1行のデータを解析します。

    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
Zamir

私のソリューションは、引用符、フィールドと文字列の区切り文字のオーバーライドなどを処理します。これは短くて便利です。

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

まず第一に、CSVとは何か、それをどのように記述するかを理解する必要があります。

(ほとんどの回答(現時点ではすべて)はこの要件を使用しないため、すべてが間違っている理由です!)

  1. すべての次の文字列(/r/n)は次の「テーブル」行です。
  2. 「表」セルは、区切り記号で区切られています。
  3. 区切り文字として任意の記号を使用できます。多くの場合、これは\t または ,
  4. 各セルには、セル内にこの区切り記号を含めることができます(セルは二重引用符で始まり、この場合は末尾に二重引用符が必要です)
  5. 各セルには、/r/nセル内のシンボル(セルは二重引用符で始まり、この場合は二重引用符で終わる必要があります)

しばらく前に、標準のMicrosoft.VisualBasic.FileIO 図書館。この単純なクラスを使用すると、2次元配列のように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」を使用することです。また、うまく機能する必要があります。しかし、それはもっと大きくなります。

0
Andrew