CSV dosyalarını C # ile başlık ile ayrıştırma


266

C # CSV dosyalarını ayrıştırmak için varsayılan / resmi / önerilen bir yolu var mı? Kendi ayrıştırıcımı döndürmek istemiyorum.

Ayrıca, Metin sürücüsü aracılığıyla CSV okumak için ODBC / OLE DB kullanan kişilerin örneklerini gördüm ve birçok insan "dezavantajları" nedeniyle bunu caydırıyor. Bu dezavantajlar nelerdir?

İdeal olarak, başlık / alan adları olarak ilk kaydı kullanarak CSV'yi sütun adına göre okuyabileceğim bir yol arıyorum. Verilen cevaplardan bazıları doğrudur, ancak temel olarak dosyayı sınıflara ayırmak için çalışır.

Yanıtlar:


138

Bırakın bir kütüphane sizin için tüm cesur ayrıntılarla başa çıksın! :-)

FileHelpers'a göz atın ve KURU kalın - Kendinizi tekrar etmeyin - tekerleği gazillionth kez yeniden icat etmeye gerek yok ....

Temel olarak, verilerinizin şeklini - CSV'deki bireysel satırınızdaki alanlar - bir genel sınıf (ve varsayılan değerler, NULL değerlerin yerine geçmesi vb. Gibi iyi düşünülmüş özellikler), nokta ile tanımlamanız gerekir. bir dosyadaki FileHelpers motoru ve tombala - bu dosyadaki tüm girdileri geri alırsınız. Tek bir basit işlem - mükemmel performans!


1
sth gerçekten özel olana kadar (ve çoğu zaten uzantı olarak uygulanabilir) FileHelpers, gitmek için en iyi yoldur, gerçekten kullanışlı, test edilmiş ve iyi performans gösteren bir çözümdür
mikus

3
1 Haziran 2015 itibariyle FileHelpers'ı indirebilmemin tek yolu sourceforge.net'te aramaktı. Kullanılan bağlantı
şöyledir

2
@dotnetguy 3.1 sürümünde (şu anda 3.1-rc2) çıkış yolundayız. Ayrıca siteyi yeniden tasarladık: www.filehelpers.net buradan en son sürümü indirebilirsiniz
Marcos Meli

1
@MarcosMeli çok teşekkürler! Projelerimden birinde FileHelpers'ı zaten kullandım ve takım için kudos kullanmak çok kolay oldu. Yakında bir blog planlıyorum ve btw - Yeni siteyi seviyorum - aferin!
Sudhanshu Mishra

FileHelpers, CSV'lerde alıntılanan virgülleri düzgün işlemez veya sütunların türünüzde bildirilen alanlarla aynı sırada olmasını beklerken alan başlıklarını eşleştirir. Şahsen kullanmazdım.
Alastair Maw

358

CSV ayrıştırıcısı artık .NET Framework'ün bir parçasıdır.

Microsoft.VisualBasic.dll dosyasına bir başvuru ekleyin (C # 'da iyi çalışır, adı aldırmayın)

using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    while (!parser.EndOfData)
    {
        //Process row
        string[] fields = parser.ReadFields();
        foreach (string field in fields)
        {
            //TODO: Process field
        }
    }
}

Dokümanlar burada - TextFieldParser Sınıfı

Not: Bir CSV ihracatçısına ihtiyacınız varsa , CsvExport'u deneyin (discl: Katkıda bulunanlardan biriyim)


2
Deneyimlerime göre TextFieldParser büyük (örn.> 250Mb) dosyalarla iyi performans göstermez. :(
MBoros

6
TextFieldParser IDisposable uygular, bu nedenle bunu bir kullanma yan tümcesinde kullanmak en iyisi olabilir. Aksi takdirde iyi cevap.
Chris Bush

3
Yapıcıda, varsayılan olarakkinden farklı bir kodlama kullanmak isteyebilirsiniz, örneğin: new TextFieldParser ("c: \ temp \ test.csv", System.Text.Encoding.UTF8)
neural5torm

1
CSV'nizdeki herhangi bir alan boş satırlar içeriyorsa, bunların atlanacağını unutmayın TextFieldParser.ReadLine(). Görmek TextFieldParser docs
mcNux

3
Bunu .NET Core'da almanın bir yolu var mı?
Hugo Zink

183

CsvHelper (bakımını yaptığım bir kütüphane) bir CSV dosyasını özel nesnelere okuyacaktır.

var csv = new CsvReader( File.OpenText( "file.csv" ) );
var myCustomObjects = csv.GetRecords<MyCustomObject>();

Bazen okumaya çalıştığınız nesnelerin sahibi olmazsınız. Bu durumda, sınıfa nitelik koyamayacağınız için akıcı eşleme kullanabilirsiniz.

public sealed class MyCustomObjectMap : CsvClassMap<MyCustomObject>
{
    public MyCustomObjectMap()
    {
        Map( m => m.Property1 ).Name( "Column Name" );
        Map( m => m.Property2 ).Index( 4 );
        Map( m => m.Property3 ).Ignore();
        Map( m => m.Property4 ).TypeConverter<MySpecialTypeConverter>();
    }
}

DÜZENLE:

CsvReader artık CultureInfo'nun büzücüye aktarılmasını gerektiriyor ( https://github.com/JoshClose/CsvHelper/issues/1441 ).

Misal:

var csv = new CsvReader(File.OpenText("file.csv"), System.Globalization.CultureInfo.CurrentCulture);

18
@ Kubal5003 ile hemfikirim. Beni sattığı şey bir NuGet paketi olarak mevcut olmanızdı. Teşekkürler dostum, hızlı ve ihtiyacım olan tüm csv okumasını yapıyor.
Gromer

7
Çok hızlı. 1,3 milyon kayıt 10 saniyede okunup serileştirildi.
marisks

2
Büyük kütüphane uygulaması çok kolay. Josh'a cevabını burada güncellemesini öneriyorum çünkü bu cevap yazıldığından beri kütüphane biraz değişti ve artık CsvHelper'i (şimdi sadece bir ad alanı) başlatamıyorsunuz ama CsvReader sınıfını kullanmanız gerekiyor.
Marko

1
CsvClassMap CsvHelper son sürümünde yok gibi görünüyor?
knocte

1
knocte, buna ClassMap deniyor. Başlık kaydı sormadan önce bir okuma yapmak zorunda gibi başka değişiklikler de vardır (bu arada ilk Read () çağrısı tarafından okunan her şeye ayarlanır). Diğerlerinin daha önce de bahsettiği gibi, süper hızlı ve çalışmak kolaydır.
norgie

31

Bir iş uygulamasında, codeproject.com, CSVReader'daki Açık Kaynak projesini kullanıyorum .

İyi çalışıyor ve iyi bir performansa sahip. Sağladığım bağlantıda bazı kıyaslama var.

Proje sayfasından kopyalanan basit bir örnek:

using (CsvReader csv = new CsvReader(new StreamReader("data.csv"), true))
{
    int fieldCount = csv.FieldCount;
    string[] headers = csv.GetFieldHeaders();

    while (csv.ReadNextRecord())
    {
        for (int i = 0; i < fieldCount; i++)
            Console.Write(string.Format("{0} = {1};", headers[i], csv[i]));

        Console.WriteLine();
    }
}

Gördüğünüz gibi, çalışmak çok kolay.



12

Sadece csv dosyalarını okumanız gerekiyorsa o zaman bu kütüphaneyi tavsiye ederim: Hızlı CSV Okuyucu
Eğer csv dosyaları oluşturmanız gerekiyorsa o zaman bunu kullanın: FileHelpers

Her ikisi de ücretsiz ve açık kaynaklıdır.


FileHelpers'ın çekici bir özeti vardır: filehelpers.com FileHelpers, dosyalar, dizeler veya akışlardaki sabit uzunluktaki veya sınırlandırılmış kayıtları içe / dışa aktarmak için ücretsiz ve kullanımı kolay bir .NET kütüphanesidir.
AnneTheAgile

Bu bağlantı soruyu cevaplayabilse de, yalnızca Yığın Taşması'nda bağlantı yanıtları önerilmemektedir, bağlantının önemli kısımlarını alıp cevabınıza koyarak bu cevabı geliştirebilirsiniz, bu bağlantı değiştiğinde cevabınızın hala bir cevap olmasını sağlar veya kaldırıldı :)
WhatsThePoint

11

İşte hiç kimse bu konuya geri gelmesi durumunda sık sık kullandığım yardımcı bir sınıf (ben paylaşmak istedim).

Bunu, kullanıma hazır projelere taşımanın basitliği için kullanıyorum:

public class CSVHelper : List<string[]>
{
  protected string csv = string.Empty;
  protected string separator = ",";

  public CSVHelper(string csv, string separator = "\",\"")
  {
    this.csv = csv;
    this.separator = separator;

    foreach (string line in Regex.Split(csv, System.Environment.NewLine).ToList().Where(s => !string.IsNullOrEmpty(s)))
    {
      string[] values = Regex.Split(line, separator);

      for (int i = 0; i < values.Length; i++)
      {
        //Trim values
        values[i] = values[i].Trim('\"');
      }

      this.Add(values);
    }
  }
}

Ve şöyle kullanın:

public List<Person> GetPeople(string csvContent)
{
  List<Person> people = new List<Person>();
  CSVHelper csv = new CSVHelper(csvContent);
  foreach(string[] line in csv)
  {
    Person person = new Person();
    person.Name = line[0];
    person.TelephoneNo = line[1];
    people.Add(person);
  }
  return people;
}

[Güncellenmiş csv yardımcısı: son yeni satır karakterinin yeni bir satır oluşturduğu hata düzeltildi]


17
csv girişlerinden herhangi biri virgül (,) içeriyorsa bu kod çalışmaz.
hakan

İşleri hafif tutmak için ayırıcı olarak bir boru karakteri kullandım. '|'
Base33

mükemmel çözüm. İkinci pasaj hakkında bir soru. Kişi ne tür bir obje
Cocoa Dev

@CocoaDev İki dize özelliği içeren bir sınıftır - Name ve TelephoneNo. Tamamen örnek için olsa. Özelliklerden herhangi biri bir tamsayı ise, yalnızca düz bir dönüşüm olmalıdır (check? İle).
Base33

10

Bu çözüm resmi Microsoft.VisualBasic kullanıyor CSV'yi ayrıştırmak derlemesini .

Avantajları:

  • kaçan sınırlayıcı
  • Üstbilgiyi yok sayar
  • Döşeme boşlukları
  • yorumları yoksay

Kod:

    using Microsoft.VisualBasic.FileIO;

    public static List<List<string>> ParseCSV (string csv)
    {
        List<List<string>> result = new List<List<string>>();


        // To use the TextFieldParser a reference to the Microsoft.VisualBasic assembly has to be added to the project. 
        using (TextFieldParser parser = new TextFieldParser(new StringReader(csv))) 
        {
            parser.CommentTokens = new string[] { "#" };
            parser.SetDelimiters(new string[] { ";" });
            parser.HasFieldsEnclosedInQuotes = true;

            // Skip over header line.
            //parser.ReadLine();

            while (!parser.EndOfData)
            {
                var values = new List<string>();

                var readFields = parser.ReadFields();
                if (readFields != null)
                    values.AddRange(readFields);
                result.Add(values);
            }
        }

        return result;
    }

7

Ben yazdım TinyCsvParser en hızlı .NET ayrıştırıcılarından biri olan ve neredeyse her CSV biçimini ayrıştırmak için son derece yapılandırılabilir olan .NET için .

MIT Lisansı altında yayınlanmıştır:

Yüklemek için NuGet'i kullanabilirsiniz . Paket Yöneticisi Konsolu'nda aşağıdaki komutu çalıştırın .

PM> Install-Package TinyCsvParser

kullanım

Bir CSV dosyasında persons.csvadlarını, soyadlarını ve doğum tarihlerini içeren Kişi listemiz olduğunu düşünün .

FirstName;LastName;BirthDate
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02

Sistemimizdeki ilgili alan adı modeli buna benzeyebilir.

private class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}

TinyCsvParser kullanırken, CSV verilerindeki sütunlar ile etki alanı modelinizdeki özellik arasındaki eşlemeyi tanımlamanız gerekir.

private class CsvPersonMapping : CsvMapping<Person>
{

    public CsvPersonMapping()
        : base()
    {
        MapProperty(0, x => x.FirstName);
        MapProperty(1, x => x.LastName);
        MapProperty(2, x => x.BirthDate);
    }
}

Ve sonra CSV verilerini bir ile ayrıştırmak için eşlemeyi kullanabiliriz CsvParser.

namespace TinyCsvParser.Test
{
    [TestFixture]
    public class TinyCsvParserTest
    {
        [Test]
        public void TinyCsvTest()
        {
            CsvParserOptions csvParserOptions = new CsvParserOptions(true, new[] { ';' });
            CsvPersonMapping csvMapper = new CsvPersonMapping();
            CsvParser<Person> csvParser = new CsvParser<Person>(csvParserOptions, csvMapper);

            var result = csvParser
                .ReadFromFile(@"persons.csv", Encoding.ASCII)
                .ToList();

            Assert.AreEqual(2, result.Count);

            Assert.IsTrue(result.All(x => x.IsValid));

            Assert.AreEqual("Philipp", result[0].Result.FirstName);
            Assert.AreEqual("Wagner", result[0].Result.LastName);

            Assert.AreEqual(1986, result[0].Result.BirthDate.Year);
            Assert.AreEqual(5, result[0].Result.BirthDate.Month);
            Assert.AreEqual(12, result[0].Result.BirthDate.Day);

            Assert.AreEqual("Max", result[1].Result.FirstName);
            Assert.AreEqual("Mustermann", result[1].Result.LastName);

            Assert.AreEqual(2014, result[1].Result.BirthDate.Year);
            Assert.AreEqual(1, result[1].Result.BirthDate.Month);
            Assert.AreEqual(1, result[1].Result.BirthDate.Day);
        }
    }
}

Kullanici rehberi

Tam bir Kullanım Kılavuzu şu adreste bulunabilir:


1

İşte benim KISS uygulaması ...

using System;
using System.Collections.Generic;
using System.Text;

class CsvParser
{
    public static List<string> Parse(string line)
    {
        const char escapeChar = '"';
        const char splitChar = ',';
        bool inEscape = false;
        bool priorEscape = false;

        List<string> result = new List<string>();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < line.Length; i++)
        {
            char c = line[i];
            switch (c)
            {
                case escapeChar:
                    if (!inEscape)
                        inEscape = true;
                    else
                    {
                        if (!priorEscape)
                        {
                            if (i + 1 < line.Length && line[i + 1] == escapeChar)
                                priorEscape = true;
                            else
                                inEscape = false;
                        }
                        else
                        {
                            sb.Append(c);
                            priorEscape = false;
                        }
                    }
                    break;
                case splitChar:
                    if (inEscape) //if in escape
                        sb.Append(c);
                    else
                    {
                        result.Add(sb.ToString());
                        sb.Length = 0;
                    }
                    break;
                default:
                    sb.Append(c);
                    break;
            }
        }

        if (sb.Length > 0)
            result.Add(sb.ToString());

        return result;
    }

}

1
Bu, bir CSV dosyasında geçerli olan tırnak içine alınmış dizelerdeki satır kesmeleri ile ilgilenmez.
John Leidegren

Alex, John'un söylemeye çalıştığı şey, RFC 4180'in ( ietf.org/rfc/rfc4180.txt - Bkz. Bölüm 2 ve madde 6), bir sütunun bir sütunun ortasında etkili bir şekilde yaydığı bir CR LF'ye izin verir Bir dosyada 2 satır. Çözümünüz muhtemelen çoğu durumda iyi çalışacaktır (özellikle CSV dosyaları Excel dışına kaydedilerek oluşturulmuşsa), ancak bu uç durumu kapsamaz. Yukarıda bahsedilen CsvHelper'ın bu durumu dikkate alması gerekiyor.
David Yates

Evet, bu doğrudur, ancak CSV'nizde CR LF varsa, muhtemelen CSV kullanmamalısınız, ancak json veya xml veya sabit uzunluk formatı gibi daha uygun bir şey kullanmalısınız.
Alex Begun

1

Bir süre önce Microsoft.VisualBasickütüphaneye dayalı CSV okuma / yazma için basit bir sınıf yazmıştım . Bu basit sınıfı kullanarak 2 boyutlu dizide olduğu gibi CSV ile çalışabilirsiniz. Sınıfımı aşağıdaki bağlantıdan bulabilirsiniz: https://github.com/ukushu/DataExporter

Basit kullanım örneği:

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

Üstbilgiyi okumak için tek yapmanız gereken csv.Rows[0]hücreleri okumaktır :)


1

Basit ayrıştırma ihtiyaçları için tek kaynaklı dosya çözümü, kullanışlı. Tüm kötü kenar davaları ile ilgilenir. Yeni satır normalizasyonu ve alıntılanan dize değişmezlerinde yeni satırların ele alınması gibi. Rica ederim!

CSV dosyanızın bir başlığı varsa, ilk satırdaki sütun adlarını (ve hesaplama sütun dizinlerini) okursunuz. Bu kadar basit.

Not DumpBir LINQPad yöntemidir, size LINQPad kullanmıyorsanız o kaldırmak isteyebilirsiniz.

void Main()
{
    var file1 = "a,b,c\r\nx,y,z";
    CSV.ParseText(file1).Dump();

    var file2 = "a,\"b\",c\r\nx,\"y,z\"";
    CSV.ParseText(file2).Dump();

    var file3 = "a,\"b\",c\r\nx,\"y\r\nz\"";
    CSV.ParseText(file3).Dump();

    var file4 = "\"\"\"\"";
    CSV.ParseText(file4).Dump();
}

static class CSV
{
    public struct Record
    {
        public readonly string[] Row;

        public string this[int index] => Row[index];

        public Record(string[] row)
        {
            Row = row;
        }
    }

    public static List<Record> ParseText(string text)
    {
        return Parse(new StringReader(text));
    }

    public static List<Record> ParseFile(string fn)
    {
        using (var reader = File.OpenText(fn))
        {
            return Parse(reader);
        }
    }

    public static List<Record> Parse(TextReader reader)
    {
        var data = new List<Record>();

        var col = new StringBuilder();
        var row = new List<string>();
        for (; ; )
        {
            var ln = reader.ReadLine();
            if (ln == null) break;
            if (Tokenize(ln, col, row))
            {
                data.Add(new Record(row.ToArray()));
                row.Clear();
            }
        }

        return data;
    }

    public static bool Tokenize(string s, StringBuilder col, List<string> row)
    {
        int i = 0;

        if (col.Length > 0)
        {
            col.AppendLine(); // continuation

            if (!TokenizeQuote(s, ref i, col, row))
            {
                return false;
            }
        }

        while (i < s.Length)
        {
            var ch = s[i];
            if (ch == ',')
            {
                row.Add(col.ToString().Trim());
                col.Length = 0;
                i++;
            }
            else if (ch == '"')
            {
                i++;
                if (!TokenizeQuote(s, ref i, col, row))
                {
                    return false;
                }
            }
            else
            {
                col.Append(ch);
                i++;
            }
        }

        if (col.Length > 0)
        {
            row.Add(col.ToString().Trim());
            col.Length = 0;
        }

        return true;
    }

    public static bool TokenizeQuote(string s, ref int i, StringBuilder col, List<string> row)
    {
        while (i < s.Length)
        {
            var ch = s[i];
            if (ch == '"')
            {
                // escape sequence
                if (i + 1 < s.Length && s[i + 1] == '"')
                {
                    col.Append('"');
                    i++;
                    i++;
                    continue;
                }
                i++;
                return true;
            }
            else
            {
                col.Append(ch);
                i++;
            }
        }
        return false;
    }
}

1

Bu listeden bir diğeri, Cinchoo ETL - çoklu dosya formatlarını (CSV, düz dosya, Xml, JSON vb.) Okumak ve yazmak için açık kaynaklı bir kütüphane

Aşağıdaki örnekte CSV dosyasının hızlı bir şekilde nasıl okunacağı gösterilmektedir (POCO nesnesi gerekmez)

string csv = @"Id, Name
1, Carl
2, Tom
3, Mark";

using (var p = ChoCSVReader.LoadText(csv)
    .WithFirstLineHeader()
    )
{
    foreach (var rec in p)
    {
        Console.WriteLine($"Id: {rec.Id}");
        Console.WriteLine($"Name: {rec.Name}");
    }
}

Aşağıdaki örnek POCO nesnesini kullanarak CSV dosyasının nasıl okunacağını gösterir

public partial class EmployeeRec
{
    public int Id { get; set; }
    public string Name { get; set; }
}

static void CSVTest()
{
    string csv = @"Id, Name
1, Carl
2, Tom
3, Mark";

    using (var p = ChoCSVReader<EmployeeRec>.LoadText(csv)
        .WithFirstLineHeader()
        )
    {
        foreach (var rec in p)
        {
            Console.WriteLine($"Id: {rec.Id}");
            Console.WriteLine($"Name: {rec.Name}");
        }
    }
}

Lütfen nasıl kullanılacağına dair CodeProject'teki makalelere göz atın .


0

Unlimit, bir CSV'yi C # split () işlevini kullanarak nasıl düzgün bir şekilde bölerim ? :

string[] tokens = System.Text.RegularExpressions.Regex.Split(paramString, ",");

NOT: bu çıkış karakterli / iç içe virgül vb. İşlemez ve bu nedenle yalnızca belirli basit CSV listeleri için uygundur.


2
Bu çok kötü ve muhtemelen yavaş :)
EKS

1
Muhtemelen, ancak küçük bir parametre seti için mükemmel ve basit bir şekilde çalışır, bu nedenle geçerli ve yararlı bir çözümdür. Neden oy kullanmıyorsunuz? "Çok Kötü" biraz aşırı, değil mi?
radsdau

1
Kaçan / iç içe virgül, vb işlemez. Bazı durumlarda çalışacaktır, ancak kesinlikle tüm csv dosyaları için çalışmaz
NStuke

Haklısın; Cevabı yansıtacak şekilde düzenleyeceğim. Teşekkürler. Ama hala yeri var.
radsdau

Bu bir sql server clr dll inşa ediyorum ve bu diğer harici paketlerin hiçbirini kullanamıyorum benim kullanım durum için mükemmel çalıştı. Sadece bir dosya adı ve satır sayısı ile basit bir csv dosyasını ayrıştırmak gerekiyordu.
dubvfan87

0

Bu kod csv'yi DataTable'a okur:

public static DataTable ReadCsv(string path)
{
    DataTable result = new DataTable("SomeData");
    using (TextFieldParser parser = new TextFieldParser(path))
    {
        parser.TextFieldType = FieldType.Delimited;
        parser.SetDelimiters(",");
        bool isFirstRow = true;
        //IList<string> headers = new List<string>();

        while (!parser.EndOfData)
        {
            string[] fields = parser.ReadFields();
            if (isFirstRow)
            {
                foreach (string field in fields)
                {
                    result.Columns.Add(new DataColumn(field, typeof(string)));
                }
                isFirstRow = false;
            }
            else
            {
                int i = 0;
                DataRow row = result.NewRow();
                foreach (string field in fields)
                {
                    row[i++] = field;
                }
                result.Rows.Add(row);
            }
        }
    }
    return result;
}

1
TextFieldParser, Microsoft.VisualBasic.dll'de bulunmaktadır.
user3285954

0

Herhangi bir pasaj isterse, bir kitaplığı bağlamak veya bir paket indirmek zorunda kalmadan kodlarına girebilir. İşte yazdığım bir sürüm:

    public static string FormatCSV(List<string> parts)
    {
        string result = "";

        foreach (string s in parts)
        {
            if (result.Length > 0)
            {
                result += ",";

                if (s.Length == 0)
                    continue;
            }

            if (s.Length > 0)
            {
                result += "\"" + s.Replace("\"", "\"\"") + "\"";
            }
            else
            {
                // cannot output double quotes since its considered an escape for a quote
                result += ",";
            }
        }

        return result;
    }

    enum CSVMode
    {
        CLOSED = 0,
        OPENED_RAW = 1,
        OPENED_QUOTE = 2
    }

    public static List<string> ParseCSV(string input)
    {
        List<string> results;

        CSVMode mode;

        char[] letters;

        string content;


        mode = CSVMode.CLOSED;

        content = "";
        results = new List<string>();
        letters = input.ToCharArray();

        for (int i = 0; i < letters.Length; i++)
        {
            char letter = letters[i];
            char nextLetter = '\0';

            if (i < letters.Length - 1)
                nextLetter = letters[i + 1];

            // If its a quote character
            if (letter == '"')
            {
                // If that next letter is a quote
                if (nextLetter == '"' && mode == CSVMode.OPENED_QUOTE)
                {
                    // Then this quote is escaped and should be added to the content

                    content += letter;

                    // Skip the escape character
                    i++;
                    continue;
                }
                else
                {
                    // otherwise its not an escaped quote and is an opening or closing one
                    // Character is skipped

                    // If it was open, then close it
                    if (mode == CSVMode.OPENED_QUOTE)
                    {
                        results.Add(content);

                        // reset the content
                        content = "";

                        mode = CSVMode.CLOSED;

                        // If there is a next letter available
                        if (nextLetter != '\0')
                        {
                            // If it is a comma
                            if (nextLetter == ',')
                            {
                                i++;
                                continue;
                            }
                            else
                            {
                                throw new Exception("Expected comma. Found: " + nextLetter);
                            }
                        }
                    }
                    else if (mode == CSVMode.OPENED_RAW)
                    {
                        // If it was opened raw, then just add the quote 
                        content += letter;
                    }
                    else if (mode == CSVMode.CLOSED)
                    {
                        // Otherwise open it as a quote 

                        mode = CSVMode.OPENED_QUOTE;
                    }
                }
            }
            // If its a comma seperator
            else if (letter == ',')
            {
                // If in quote mode
                if (mode == CSVMode.OPENED_QUOTE)
                {
                    // Just read it
                    content += letter;
                }
                // If raw, then close the content
                else if (mode == CSVMode.OPENED_RAW)
                {
                    results.Add(content);

                    content = "";

                    mode = CSVMode.CLOSED;
                }
                // If it was closed, then open it raw
                else if (mode == CSVMode.CLOSED)
                {
                    mode = CSVMode.OPENED_RAW;

                    results.Add(content);

                    content = "";
                }
            }
            else
            {
                // If opened quote, just read it
                if (mode == CSVMode.OPENED_QUOTE)
                {
                    content += letter;
                }
                // If opened raw, then read it
                else if (mode == CSVMode.OPENED_RAW)
                {
                    content += letter;
                }
                // It closed, then open raw
                else if (mode == CSVMode.CLOSED)
                {
                    mode = CSVMode.OPENED_RAW;

                    content += letter;
                }
            }
        }

        // If it was still reading when the buffer finished
        if (mode != CSVMode.CLOSED)
        {
            results.Add(content);
        }

        return results;
    }

0

İşte kısa ve basit bir çözüm.

                using (TextFieldParser parser = new TextFieldParser(outputLocation))
                 {
                        parser.TextFieldType = FieldType.Delimited;
                        parser.SetDelimiters(",");
                        string[] headers = parser.ReadLine().Split(',');
                        foreach (string header in headers)
                        {
                            dataTable.Columns.Add(header);
                        }
                        while (!parser.EndOfData)
                        {
                            string[] fields = parser.ReadFields();
                            dataTable.Rows.Add(fields);
                        }
                    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.