it-swarm.asia

قراءة ملف CSV وتخزين القيم في صفيف

أحاول قراءة ملف *.csv-.

يتكون ملف *.csv- من عمودين مفصولة بفاصلة منقوطة ("؛ ").

أنا قادر على قراءة الملف *.csv- باستخدام StreamReader وقادر على فصل كل سطر باستخدام وظيفة Split(). أريد تخزين كل عمود في صفيف منفصل ثم عرضه.

هل من الممكن القيام بذلك؟

267
Rushabh Shah

يمكنك القيام بذلك مثل هذا:

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]);
        }
    }
}
334
Michael M.

محلل 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

124
Habeeb

طريقة LINQ:

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

^ ^ خاطئ - تحرير بواسطة Nick

يبدو أن المجيب الأصلي كان يحاول ملء csv بمصفوفة ثنائية الأبعاد - صفيف يحتوي على صفائف. يحتوي كل عنصر في الصفيف الأول على صفيف يمثل رقم السطر مع كل عنصر في الصفيف المتداخل الذي يحتوي على بيانات هذا العمود المحدد.

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

عادةً ما أستخدم هذا المحلل اللغوي من codeproject ، نظرًا لوجود مجموعة من الشخصيات تهرب وما شابه ذلك والتي يعالجها لي.

33
Paul

إليكم تباين الإجابة الأعلى إجابة:

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

توصلت للتو إلى هذه المكتبة: https://github.com/JoshClose/CsvHelper

بديهية جدا وسهلة الاستخدام. يحتوي على حزمة nuget أيضًا والتي تم تنفيذها بسرعة: http://nuget.org/packages/CsvHelper/1.17.0 . كما يبدو أن الحفاظ بنشاط على ما أحب.

من السهل تهيئتها لاستخدام شبه نقطتين: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

29
joshb

لا يمكنك إنشاء صفيف على الفور لأنك تحتاج إلى معرفة عدد الصفوف من البداية (وهذا سيتطلب قراءة ملف 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);

حاشية.

يرجى ملاحظة أن هذا مجرد مثال بسيط للغاية . لا يمثل استخدام string.Split الحالات التي تحتوي فيها بعض السجلات على الفاصل ; بداخلها.
للحصول على نهج أكثر أمانًا ، فكر في استخدام بعض مكتبات csv مثل CsvHelper على nuget.

25
digEmAll

إذا كنت بحاجة إلى تخطي خطوط (أو رؤوس) و/أو أعمدة ، يمكنك استخدام هذا لإنشاء صفيف ثنائي الأبعاد:

    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

يعد هذا مفيدًا جدًا إذا كنت بحاجة إلى صياغة البيانات قبل معالجتها مرة أخرى (على افتراض أن أول سطرين يتكونان من العنوان الرئيسي ، والعمود الأول هو عنوان صف - لا تحتاج إلى تضمينه في الصفيف لأنك فقط تريد أن تنظر في البيانات).

N. يمكنك بسهولة الحصول على العناوين والعمود الأول باستخدام الكود التالي:

    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 الخاص بك:

CSV Matrix

ملاحظة: إذا كنت بحاجة إلى تخطي الصفوف الفارغة - والتي يمكن بسهولة في بعض الأحيان ، يمكنك القيام بذلك عن طريق إدخال

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

بين from و select عبارة فيLINQأمثلة التعليمات البرمجية أعلاه.

11
Matt

يمكنك استخدام Microsoft.VisualBasic.FileIO.TextFieldParser dll في C # لتحسين الأداء

الحصول على أدناه رمز المثال من المادة أعلاه

static void Main()
{
    string [email protected]"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;
}
9
kombsh

مرحبًا بكم جميعًا ، لقد قمت بإنشاء فصل ثابت للقيام بذلك. + التحقق من العمود + إزالة علامة الحصص

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

}
4
Mathias Schmidt
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();
4
Jakub Konecki

في ما يلي حالة خاصة حيث يحتوي أحد حقول البيانات على فاصلة منقوطة ("؛") كجزء من بياناته في هذه الحالة ستفشل معظم الإجابات أعلاه.

حل سيكون هذه الحالة

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

يسمح المصدر المفتوح Angara.Table library بتحميل ملف CSV في أعمدة مكتوبة ، بحيث يمكنك الحصول على المصفوفات من الأعمدة. يمكن فهرسة كل عمود بالاسم أو الفهرس. راجع http://predictionmachines.github.io/Angara.Table/saveload.html .

تتبع المكتبة RFC4180 لـ CSV ؛ أنها تتيح الاستدلال النوعي والسلاسل المتعددة الأسطر.

مثال:

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 Assembly؛ انقر فوق "إضافة مرجع" في المشروع واختر FSharp.Core 4.4 ضمن "التجميعات" -> "الامتدادات".

2
Dmitry Voytsekhovskiy

أنا مجرد طالب يعمل على أطروحة الماجستير الخاصة بي ، ولكن هذه هي الطريقة التي قمت بحلها وعملت بشكل جيد بالنسبة لي. عليك أولاً تحديد ملفك من الدليل (فقط بتنسيق 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
        );
    }
}
1
Daniel

لقد كنت أستخدم 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] ...
}
1
Oliver Bock

لا يزال خطأ. تحتاج إلى التعويض عن "" في علامات اقتباس. هنا حل بلدي مايكروسوفت نمط 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;
    }
}
0
R Keene

أمضيت ساعات قليلة في البحث عن مكتبة مناسبة ، لكنني أخيرًا كتبت الرمز الخاص بي :) يمكنك قراءة الملف (أو قاعدة البيانات) بأي أدوات تريدها ثم تطبيق الروتين التالي على كل سطر:

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();
}
0
Zbyszek Swirski

لدي مكتبة تقوم بها بالضبط.

منذ بعض الوقت كنت قد كتبت مكتبة بسيطة وسريعة بما يكفي للعمل مع ملفات CSV. يمكنك العثور عليه من خلال الرابط التالي: https://github.com/ukushu/DataExporter

وهو يعمل مع CSV مثل مع مجموعة 2 الأبعاد. بالضبط مثل ما تحتاجه.

على سبيل المثال ، في حالة احتياجك لجميع قيم الصف الثالث فقط ، تحتاج إلى كتابة:

Csv csv = new Csv();

csv.FileOpen("c:\\file1.csv");

var allValuesOf3rdRow = csv.Rows[2];

أو لقراءة الخلية الثانية من

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