2008-09-22 22 views
14

C# uygulamasında, bir CSV dosyasını okumak için Microsoft Jet OLEDB veri sağlayıcısı kullanıyorum. Bağlantı dizesi aşağıdaki gibi görünür: DataReader ve OLEDB Jet veri sağlayıcısı kullanarak bir CSV dosyası okurken, sütun veri türlerini nasıl kontrol edebilirim?

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Data;Extended Properties="text;HDR=Yes;FMT=Delimited 

O bağlantı dizesini kullanarak bir ADO.NET OleDbConnection açın ve CSV komutuyla dosya tüm satırları seçin:

select * from Data.csv 

Bir OleDbDataReader açtığınızda ve döndürdüğü sütunların veri türlerini inceler, yığındaki bir şeyin, dosyadaki ilk veri satırı temelinde veri türlerinde tahmin etmeye çalıştığını buldum. Örneğin, CSV dosyası içerdiğini düşünelim: Ev sütunu için OleDbDataReader.GetDataTypeName yöntemin çağrılması

House,Street,Town 
123,Fake Street,Springfield 
12a,Evergreen Terrace,Springfield 

sütun veri türü "DBTYPE_I4" verildiğini ortaya çıkaracaktır, bu yüzden okunan tüm değerler olarak yorumlanır tamsayılar. Benim sorunum House bir dize olmalı - İkinci satırda House değerini okumaya çalıştığımda, OleDbDataReader boş döndürür.

Jet veritabanı sağlayıcısı veya OleDbDataReader'dan bir sütunu sayı yerine dizeler olarak yorumlamasını nasıl söyleyebilirim? yürürlükte bunu bir yapı verir -

cevap

11

Marc'ın yanıta genişletmek için, ben Schema.ini adlı bir metin dosyası oluşturun ve CSV dosyası olarak aynı dizinde koymak gerekir. onlar dosyasında yer değilseniz yanı sütun türleri olarak, bu dosya dosya biçimini, tarih saat biçimini, bölgesel ayarları ve sütun adları belirtebilirsiniz.

ben soru çalışmalarında verdi örneğini yapmak için, şema dosyası bu gibi görünmelidir:

[Data.csv] 
ColNameHeader=True 
Col1=House Text 
Col2=Street Text 
Col3=Town Text 
Ben de çalışmadan önce veri sağlayıcı dosyasındaki tüm satırları incelemek yapmak için bu deneyebilirsiniz

veri türlerini tahmin etmeye: dinamik adlarla dosyalarından gerçek hayatta

[Data.csv] 
ColNameHeader=true 
MaxScanRows=0 

, başvurum ithalatı verileri, bu yüzden anında bir Schema.ini dosyası oluşturmak ve CSV ile aynı dizine yazmak zorunda bağlantımı açmadan önce dosya. http://msdn.microsoft.com/en-us/library/ms709353(VS.85).aspx - -

fazla ayrıntı burada bulabilirsiniz veya "Schema.ini dosyasında" için MSDN Kitaplığı arayarak.

5

Sen şema belirlemek için tüm satırları taramak için sürücü söylemek gerekir

http://kbcsv.codeplex.com/

using (var reader = new CsvReader("data.csv")) 
{ 
    reader.ReadHeaderRecord(); 
    foreach (var record in reader.DataRecords) 
    { 
     var name = record["Name"]; 
     var age = record["Age"]; 
    } 
} 
+0

Bu, OleDbProvider ürününü tamamen devre dışı bırakacaktır; bu muhtemelen iyi bir şeydir. Kayıt ["FieldName"] 'den döndürülen değerler tüm dizelerdir - kodumun her sütuntan hangi veri türünün beklendiğini önceden bilmesi ve dizeleri" System.Convert "üzerinden çalıştırması gerekir. –

0

kontrol edin. Aksi takdirde, ilk birkaç satır sayısalsa ve kalanlar alfasayısal ise, alfasayısal hücreler boş olacaktır.

Rory gibi, bir schema.ini dosyasını dinamik olarak oluşturmam gerektiğini, çünkü sürücünün programa göre tüm satırları taramasını sağlamanın bir yolu olmadığını buldum.

public static DataTable GetDataFromCsvFile(string filePath, bool isFirstRowHeader = true) 
    { 
     if (!File.Exists(filePath)) 
     { 
      throw new FileNotFoundException("The path: " + filePath + " doesn't exist!"); 
     } 

     if (!(Path.GetExtension(filePath) ?? string.Empty).ToUpper().Equals(".CSV")) 
     { 
      throw new ArgumentException("Only CSV files are supported"); 
     } 
     var pathOnly = Path.GetDirectoryName(filePath); 
     var filename = Path.GetFileName(filePath); 
     var schemaIni = 
      $"[{filename}]{Environment.NewLine}" + 
      $"Format=CSVDelimited{Environment.NewLine}" + 
      $"ColNameHeader={(isFirstRowHeader ? "True" : "False")}{Environment.NewLine}" + 
      $"MaxScanRows=0{Environment.NewLine}" + 
      $" ; scan all rows for data type{Environment.NewLine}" + 
      $" ; This file was automatically generated"; 
     var schemaFile = pathOnly != null ? Path.Combine(pathOnly, "schema.ini") : "schema.ini"; 
     File.WriteAllText(schemaFile, schemaIni); 

     try 
     { 
      var sqlCommand = [email protected]"SELECT * FROM [{filename}]"; 

      var oleDbConnString = 
       $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={pathOnly};Extended Properties=\"Text;HDR={(isFirstRowHeader ? "Yes" : "No")}\""; 

      using (var oleDbConnection = new OleDbConnection(oleDbConnString)) 
      using (var adapter = new OleDbDataAdapter(sqlCommand, oleDbConnection)) 
      using (var dataTable = new DataTable()) 
      { 
       adapter.FillSchema(dataTable, SchemaType.Source); 
       adapter.Fill(dataTable); 
       return dataTable; 
      } 
     } 
     finally 
     { 
      if (File.Exists(schemaFile)) 
      { 
       File.Delete(schemaFile); 
      } 
     } 
    } 

Sen eğer bazı değişiklik yapmanız gerekir: Bir kod örneği Eğer schema.ini İşte

yılında MaxScanRows=0 olmalıdır

oluyor (bu excel dosyaları için geçerli değildir) Bunu aynı dizinde aynı anda birden fazla iş parçacığında çalıştırıyor.

İlgili konular