Mengingat ini dibuat setahun lebih awal dari 1103495, saya pikir pertanyaan itu adalah duplikat dari pertanyaan ini.
MattH
2
Terima kasih, Matt. Saya hanya mencoba menghubungkan mereka, bukan menunjukkan mana yang lebih dulu. Anda akan melihat bahwa saya memiliki teks yang persis sama pada pertanyaan lain yang menunjuk pada pertanyaan ini. Adakah cara yang lebih baik untuk menyatukan dua pertanyaan?
TextFieldParser Microsoft stabil dan mengikuti RFC 4180 untuk file CSV. Jangan menunda Microsoft.VisualBasicnamespace; itu adalah komponen standar dalam .NETFramework, cukup tambahkan referensi ke Microsoft.VisualBasicrakitan global .
Jika Anda mengompilasi untuk Windows (bukan Mono) dan tidak mengantisipasi keharusan mengurai file CSV yang "rusak" (tidak sesuai RFC), maka ini akan menjadi pilihan yang jelas, karena gratis, tidak terbatas, stabil, dan didukung secara aktif, sebagian besar tidak dapat dikatakan untuk FileHelpers.
Sebenarnya tidak ada VB khusus tentang kelas ini selain namespace sayangnya dinamai. Saya pasti akan memilih pustaka ini jika saya hanya membutuhkan parser CSV "sederhana", karena tidak ada yang perlu diunduh, didistribusikan, atau dikhawatirkan secara umum. Untuk itu, saya telah mengedit frase yang berfokus pada VB dari jawaban ini.
Aaronaught
@Aaronaught Saya pikir hasil edit Anda sebagian besar merupakan peningkatan. Meskipun RFC belum tentu berwibawa, karena banyak penulis CSV tidak mematuhinya, misalnya Excel tidak selalu menggunakan koma dalam file "CSV". Juga bukankah jawaban saya sebelumnya sudah mengatakan bahwa kelas dapat digunakan dari C #?
MarkJ
Ini TextFieldParserakan bekerja untuk tab-delimited dan cruft aneh lain yang dihasilkan Excel juga. Saya menyadari bahwa jawaban Anda sebelumnya tidak mengklaim bahwa pustaka itu khusus VB, itu baru saja menurut saya menyiratkan bahwa itu benar-benar dimaksudkan untuk VB, dan tidak dimaksudkan untuk digunakan dari C #, yang menurut saya tidak kasus - ada beberapa kelas yang sangat berguna di MSVB.
Ini membutuhkan akses sistem file. Sejauh yang saya tahu tidak ada cara untuk membuat OLEDB berfungsi dengan aliran dalam memori :(
UserControl
3
@UserControl, tentu saja ini memerlukan akses sistem file. Dia bertanya tentang mengimpor file CSV
Kevin
1
Saya tidak mengeluh. Sebenarnya saya lebih suka solusi OLEDB daripada yang lain tetapi saya sering kali frustrasi ketika perlu mengurai CSV dalam aplikasi ASP.NET jadi ingin mencatatnya.
UserControl
12
Jika Anda mengharapkan skenario yang cukup rumit untuk penguraian CSV, jangan pernah berpikir untuk menggulung parser kami sendiri . Ada banyak alat luar biasa di luar sana, seperti FileHelpers , atau bahkan dari CodeProject .
Intinya adalah ini adalah masalah yang cukup umum dan Anda dapat bertaruh bahwa banyak pengembang perangkat lunak telah memikirkan dan memecahkan masalah ini.
Meskipun tautan ini mungkin menjawab pertanyaan, lebih baik menyertakan bagian penting dari jawaban di sini dan menyediakan tautan untuk referensi. Jawaban link saja bisa menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
techspider
Terima kasih @techspider Saya harap Anda memperhatikan bahwa posting ini berasal dari periode beta StackOverflow: D Yang sedang dikatakan saat ini alat CSV lebih baik bersumber dari paket Nuget - jadi saya tidak yakin apakah jawaban tautan pun kebal dari 8 tahun -siklus evolusi teknologi yang lama
Jon Limjap
9
Brian memberikan solusi yang bagus untuk mengubahnya menjadi koleksi yang diketik dengan kuat.
Sebagian besar metode penguraian CSV yang diberikan tidak memperhitungkan bidang pelolosan atau beberapa seluk-beluk file CSV lainnya (seperti bidang pemangkasan). Berikut adalah kode yang saya gunakan secara pribadi. Ini agak kasar di sekitar tepinya dan hampir tidak ada pelaporan kesalahan.
publicstaticIList<IList<string>>Parse(string content){IList<IList<string>> records =newList<IList<string>>();StringReader stringReader =newStringReader(content);bool inQoutedString =false;IList<string> record =newList<string>();StringBuilder fieldBuilder =newStringBuilder();while(stringReader.Peek()!=-1){char readChar =(char)stringReader.Read();if(readChar =='\n'||(readChar =='\r'&& stringReader.Peek()=='\n')){// If it's a \r\n combo consume the \n part and throw it away.if(readChar =='\r'){
stringReader.Read();}if(inQoutedString){if(readChar =='\r'){
fieldBuilder.Append('\r');}
fieldBuilder.Append('\n');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();
records.Add(record);
record =newList<string>();
inQoutedString =false;}}elseif(fieldBuilder.Length==0&&!inQoutedString){if(char.IsWhiteSpace(readChar)){// Ignore leading whitespace}elseif(readChar =='"'){
inQoutedString =true;}elseif(readChar ==','){
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}else{
fieldBuilder.Append(readChar);}}elseif(readChar ==','){if(inQoutedString){
fieldBuilder.Append(',');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}}elseif(readChar =='"'){if(inQoutedString){if(stringReader.Peek()=='"'){
stringReader.Read();
fieldBuilder.Append('"');}else{
inQoutedString =false;}}else{
fieldBuilder.Append(readChar);}}else{
fieldBuilder.Append(readChar);}}
record.Add(fieldBuilder.ToString().TrimEnd());
records.Add(record);return records;}
Perhatikan bahwa ini tidak menangani kasus tepi bidang yang tidak dihilangkan oleh tanda kutip ganda, tetapi meerley memiliki string yang dikutip di dalamnya. Lihat posting ini untuk sedikit penjelasan yang lebih baik serta beberapa tautan ke beberapa perpustakaan yang tepat.
Saya setuju dengan @ NotMyself . FileHelpers telah teruji dengan baik dan menangani semua jenis kasus tepi yang pada akhirnya harus Anda tangani jika Anda melakukannya sendiri. Lihatlah apa yang FileHelpers lakukan dan hanya tulis sendiri jika Anda benar-benar yakin bahwa (1) Anda tidak akan pernah perlu menangani kasus edge yang dilakukan FileHelpers, atau (2) Anda suka menulis hal semacam ini dan akan melakukannya sangat senang ketika Anda harus mengurai hal-hal seperti ini:
1, "Bill", "Smith", "Supervisor", "No Comment"
2, 'Drake,', 'O'Malley', "Petugas kebersihan,
Ups, saya tidak dikutip dan saya berada di jalur baru!
Saya bosan jadi saya memodifikasi beberapa hal yang saya tulis. Ini mencoba untuk merangkum parsing dengan cara OO sementara mengurangi jumlah iterasi melalui file, itu hanya iterasi sekali di bagian depan atas.
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespaceConsoleApplication1{classProgram{staticvoidMain(string[] args){// usage:// note this wont run as getting streams is not Implemented// but will get you startedCSVFileParser fileParser =newCSVFileParser();// TO Do: configure fileparserPersonParser personParser =newPersonParser(fileParser);List<Person> persons =newList<Person>();// if the file is large and there is a good way to limit// without having to reparse the whole file you can use a // linq query if you desireforeach(Person person in personParser.GetPersons()){
persons.Add(person);}// now we have a list of Person objects}}publicabstractclassCSVParser{protectedString[] deliniators ={","};protectedinternalIEnumerable<String[]>GetRecords(){Stream stream =GetStream();StreamReader reader =newStreamReader(stream);String[] aRecord;while(!reader.EndOfStream){
aRecord = reader.ReadLine().Split(deliniators,StringSplitOptions.None);yieldreturn aRecord;}}protectedabstractStreamGetStream();}publicclassCSVFileParser:CSVParser{// to do: add logic to get a stream from a fileprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassCSVWebParser:CSVParser{// to do: add logic to get a stream from a web requestprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassPerson{publicStringName{get;set;}publicStringAddress{get;set;}publicDateTime DOB {get;set;}}publicclassPersonParser{publicPersonParser(CSVParser parser){this.Parser= parser;}publicCSVParserParser{get;set;}publicIEnumerable<Person>GetPersons(){foreach(String[] record inthis.Parser.GetRecords()){yieldreturnnewPerson(){Name= record[0],Address= record[1],
DOB =DateTime.Parse(record[2]),};}}}}
Cara sederhana yang baik untuk melakukannya adalah dengan membuka file, dan membaca setiap baris ke dalam array, daftar tertaut, struktur data pilihan Anda. Berhati-hatilah saat menangani baris pertama.
Ini mungkin tidak masuk akal, tetapi tampaknya ada cara langsung untuk mengaksesnya juga dengan menggunakan string koneksi .
Mengapa tidak mencoba menggunakan Python, bukan C # atau VB? Ini memiliki modul CSV yang bagus untuk diimpor yang melakukan semua pekerjaan berat untuk Anda.
Jangan melompat ke python dari VB demi parser CSV. Ada satu di VB. Meski anehnya tampaknya hal itu diabaikan dalam jawaban atas pertanyaan ini. msdn.microsoft.com/en-us/library/…
MarkJ
1
Saya harus menggunakan parser CSV di .NET untuk proyek musim panas ini dan memilih Microsoft Jet Text Driver. Anda menentukan folder menggunakan string koneksi, lalu membuat kueri file menggunakan pernyataan SQL Select. Anda dapat menentukan tipe yang kuat menggunakan file schema.ini. Saya tidak melakukan ini pada awalnya, tetapi kemudian saya mendapatkan hasil yang buruk di mana jenis datanya tidak langsung terlihat, seperti nomor IP atau entri seperti "XYQ 3.9 SP1".
Satu batasan yang saya temui adalah tidak dapat menangani nama kolom di atas 64 karakter; itu memotong. Ini seharusnya tidak menjadi masalah, kecuali saya berurusan dengan data masukan yang dirancang dengan sangat buruk. Ia mengembalikan ADO.NET DataSet.
Ini adalah solusi terbaik yang saya temukan. Saya akan berhati-hati dalam menjalankan pengurai CSV saya sendiri, karena saya mungkin akan melewatkan beberapa kasus akhir, dan saya tidak menemukan paket penguraian CSV gratis lainnya untuk .NET di luar sana.
EDIT: Juga, hanya ada satu file schema.ini per direktori, jadi saya secara dinamis menambahkannya untuk mengetik kolom yang dibutuhkan. Ini hanya akan mengetik kuat kolom yang ditentukan, dan menyimpulkan untuk setiap bidang yang tidak ditentukan. Saya sangat menghargai ini, karena saya berurusan dengan mengimpor CSV kolom 70+ yang lancar dan tidak ingin menentukan setiap kolom, hanya kolom yang berperilaku tidak semestinya.
Mungkin ada perpustakaan yang bisa Anda gunakan untuk membantu, tapi itu mungkin sesederhana yang bisa Anda dapatkan. Pastikan Anda tidak memiliki koma dalam data, jika tidak, Anda perlu menguraikannya dengan lebih baik.
Jawaban:
TextFieldParser Microsoft stabil dan mengikuti RFC 4180 untuk file CSV. Jangan menunda
Microsoft.VisualBasic
namespace; itu adalah komponen standar dalam .NETFramework, cukup tambahkan referensi keMicrosoft.VisualBasic
rakitan global .Jika Anda mengompilasi untuk Windows (bukan Mono) dan tidak mengantisipasi keharusan mengurai file CSV yang "rusak" (tidak sesuai RFC), maka ini akan menjadi pilihan yang jelas, karena gratis, tidak terbatas, stabil, dan didukung secara aktif, sebagian besar tidak dapat dikatakan untuk FileHelpers.
Lihat juga: Cara: Membaca Dari File Teks Berbatas Koma dalam Visual Basic untuk contoh kode VB.
sumber
TextFieldParser
akan bekerja untuk tab-delimited dan cruft aneh lain yang dihasilkan Excel juga. Saya menyadari bahwa jawaban Anda sebelumnya tidak mengklaim bahwa pustaka itu khusus VB, itu baru saja menurut saya menyiratkan bahwa itu benar-benar dimaksudkan untuk VB, dan tidak dimaksudkan untuk digunakan dari C #, yang menurut saya tidak kasus - ada beberapa kelas yang sangat berguna di MSVB.Gunakan koneksi OleDB.
sumber
Jika Anda mengharapkan skenario yang cukup rumit untuk penguraian CSV, jangan pernah berpikir untuk menggulung parser kami sendiri . Ada banyak alat luar biasa di luar sana, seperti FileHelpers , atau bahkan dari CodeProject .
Intinya adalah ini adalah masalah yang cukup umum dan Anda dapat bertaruh bahwa banyak pengembang perangkat lunak telah memikirkan dan memecahkan masalah ini.
sumber
Brian memberikan solusi yang bagus untuk mengubahnya menjadi koleksi yang diketik dengan kuat.
Sebagian besar metode penguraian CSV yang diberikan tidak memperhitungkan bidang pelolosan atau beberapa seluk-beluk file CSV lainnya (seperti bidang pemangkasan). Berikut adalah kode yang saya gunakan secara pribadi. Ini agak kasar di sekitar tepinya dan hampir tidak ada pelaporan kesalahan.
Perhatikan bahwa ini tidak menangani kasus tepi bidang yang tidak dihilangkan oleh tanda kutip ganda, tetapi meerley memiliki string yang dikutip di dalamnya. Lihat posting ini untuk sedikit penjelasan yang lebih baik serta beberapa tautan ke beberapa perpustakaan yang tepat.
sumber
Saya setuju dengan @ NotMyself . FileHelpers telah teruji dengan baik dan menangani semua jenis kasus tepi yang pada akhirnya harus Anda tangani jika Anda melakukannya sendiri. Lihatlah apa yang FileHelpers lakukan dan hanya tulis sendiri jika Anda benar-benar yakin bahwa (1) Anda tidak akan pernah perlu menangani kasus edge yang dilakukan FileHelpers, atau (2) Anda suka menulis hal semacam ini dan akan melakukannya sangat senang ketika Anda harus mengurai hal-hal seperti ini:
1, "Bill", "Smith", "Supervisor", "No Comment"
2, 'Drake,', 'O'Malley', "Petugas kebersihan,
Ups, saya tidak dikutip dan saya berada di jalur baru!
sumber
Saya bosan jadi saya memodifikasi beberapa hal yang saya tulis. Ini mencoba untuk merangkum parsing dengan cara OO sementara mengurangi jumlah iterasi melalui file, itu hanya iterasi sekali di bagian depan atas.
sumber
Ada dua artikel di CodeProject yang menyediakan kode untuk solusi, satu yang menggunakan StreamReader dan satu lagi yang mengimpor data CSV menggunakan Microsoft Text Driver .
sumber
Cara sederhana yang baik untuk melakukannya adalah dengan membuka file, dan membaca setiap baris ke dalam array, daftar tertaut, struktur data pilihan Anda. Berhati-hatilah saat menangani baris pertama.
Ini mungkin tidak masuk akal, tetapi tampaknya ada cara langsung untuk mengaksesnya juga dengan menggunakan string koneksi .
Mengapa tidak mencoba menggunakan Python, bukan C # atau VB? Ini memiliki modul CSV yang bagus untuk diimpor yang melakukan semua pekerjaan berat untuk Anda.
sumber
Saya harus menggunakan parser CSV di .NET untuk proyek musim panas ini dan memilih Microsoft Jet Text Driver. Anda menentukan folder menggunakan string koneksi, lalu membuat kueri file menggunakan pernyataan SQL Select. Anda dapat menentukan tipe yang kuat menggunakan file schema.ini. Saya tidak melakukan ini pada awalnya, tetapi kemudian saya mendapatkan hasil yang buruk di mana jenis datanya tidak langsung terlihat, seperti nomor IP atau entri seperti "XYQ 3.9 SP1".
Satu batasan yang saya temui adalah tidak dapat menangani nama kolom di atas 64 karakter; itu memotong. Ini seharusnya tidak menjadi masalah, kecuali saya berurusan dengan data masukan yang dirancang dengan sangat buruk. Ia mengembalikan ADO.NET DataSet.
Ini adalah solusi terbaik yang saya temukan. Saya akan berhati-hati dalam menjalankan pengurai CSV saya sendiri, karena saya mungkin akan melewatkan beberapa kasus akhir, dan saya tidak menemukan paket penguraian CSV gratis lainnya untuk .NET di luar sana.
EDIT: Juga, hanya ada satu file schema.ini per direktori, jadi saya secara dinamis menambahkannya untuk mengetik kolom yang dibutuhkan. Ini hanya akan mengetik kuat kolom yang ditentukan, dan menyimpulkan untuk setiap bidang yang tidak ditentukan. Saya sangat menghargai ini, karena saya berurusan dengan mengimpor CSV kolom 70+ yang lancar dan tidak ingin menentukan setiap kolom, hanya kolom yang berperilaku tidak semestinya.
sumber
Saya mengetik beberapa kode. Hasil di datagridviewer terlihat bagus. Ini mem-parsing satu baris teks ke daftar objek.
sumber
Jika Anda dapat menjamin bahwa tidak ada koma dalam data, cara termudah mungkin adalah dengan menggunakan String.split .
Sebagai contoh:
Mungkin ada perpustakaan yang bisa Anda gunakan untuk membantu, tapi itu mungkin sesederhana yang bisa Anda dapatkan. Pastikan Anda tidak memiliki koma dalam data, jika tidak, Anda perlu menguraikannya dengan lebih baik.
sumber