2008-09-22 30 views
14

Trong ứng dụng C# của tôi, tôi đang sử dụng nhà cung cấp dữ liệu Microsoft Jet OLEDB để đọc tệp CSV. Chuỗi kết nối trông như thế này:Khi đọc tệp CSV bằng cách sử dụng DataReader và nhà cung cấp dữ liệu OLEDB Jet, làm cách nào tôi có thể kiểm soát các loại dữ liệu cột?

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

tôi mở một OleDbConnection ADO.NET sử dụng rằng chuỗi kết nối và chọn tất cả các hàng từ nộp với lệnh CSV:

select * from Data.csv 

Khi tôi mở một OleDbDataReader và kiểm tra các kiểu dữ liệu của các cột nó trả về, tôi thấy rằng một cái gì đó trong ngăn xếp đã cố gắng đoán tại các kiểu dữ liệu dựa trên hàng đầu tiên của dữ liệu trong tệp. Ví dụ, giả sử các tập tin CSV chứa:

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

Gọi phương thức OleDbDataReader.GetDataTypeName cho cột nhà sẽ tiết lộ rằng cột đã được trao kiểu dữ liệu "DBTYPE_I4", vì vậy tất cả các giá trị đọc từ nó được hiểu là số nguyên. Vấn đề của tôi là House phải là một chuỗi - khi tôi cố gắng đọc giá trị House từ hàng thứ hai, OleDbDataReader trả về null.

Làm cách nào để tôi có thể yêu cầu nhà cung cấp cơ sở dữ liệu máy bay phản lực hoặc OleDbDataReader diễn giải cột dưới dạng chuỗi thay vì số?

Trả lời

11

Để mở rộng về câu trả lời của Marc, tôi cần phải tạo ra một tập tin văn bản gọi là schema.ini và đặt nó trong cùng thư mục với tập tin CSV. Cũng như các kiểu cột, tệp này có thể chỉ định định dạng tệp, định dạng ngày giờ, cài đặt khu vực và tên cột nếu chúng không được bao gồm trong tệp.

Để thực hiện các ví dụ tôi đã vào công việc câu hỏi, file Schema sẽ trông như thế này:

[Data.csv] 
ColNameHeader=True 
Col1=House Text 
Col2=Street Text 
Col3=Town Text 

tôi cũng có thể thử này để làm cho các nhà cung cấp dữ liệu kiểm tra tất cả các hàng trong tập tin trước khi nó cố gắng đoán các kiểu dữ liệu:

[Data.csv] 
ColNameHeader=true 
MaxScanRows=0 

Trong cuộc sống thực, dữ liệu nhập khẩu ứng dụng của tôi từ các tập tin với những cái tên năng động, vì vậy tôi phải tạo một tập tin schema.ini khi đang bay và ghi nó vào cùng thư mục với CSV trước khi mở kết nối.

Chi tiết khác có thể tìm thấy tại đây - http://msdn.microsoft.com/en-us/library/ms709353(VS.85).aspx - hoặc bằng cách tìm kiếm Thư viện MSDN cho "tệp Schema.ini".

5

Vui lòng kiểm tra

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

Điều này sẽ vượt qua OleDbProvider hoàn toàn, mà có lẽ là một điều tốt. Các giá trị được trả về từ 'record [" FieldName "]' là tất cả các chuỗi - mã của tôi sẽ cần phải biết trước kiểu dữ liệu nào được mong đợi từ mỗi cột và chạy các chuỗi thông qua 'System.Convert'. –

0

Bạn cần phải nói với người lái xe để quét tất cả các hàng để xác định các lược đồ. Nếu không, nếu một vài hàng đầu tiên là số và phần còn lại là chữ và số, các ô chữ và số sẽ trống.

Giống như Rory, tôi thấy rằng tôi cần tạo tệp schema.ini động vì không có cách nào để báo cho trình điều khiển biết cách quét tất cả các hàng.(Đây không phải là trường hợp cho các tập tin excel)

Bạn phải có MaxScanRows=0 trong schema.ini bạn

Dưới đây là một ví dụ mã:

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

Bạn sẽ cần phải thực hiện một số thay đổi nếu bạn là chạy trên cùng một thư mục trong nhiều chủ đề cùng một lúc.

Các vấn đề liên quan