2009-09-22 235 views
24

我似乎無法使用下面的連接字符串來讀取.csv文件:C#閱讀csv文件給出了不是有效的路徑

var fileName = string.Format("{0}{1}", AppDomain.CurrentDomain.BaseDirectory, "Uploads\\countrylist.csv"); 
string connectionString = string.Format(@"Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}; Extended Properties=""text;HDR=YES;FMT=Delimited""", fileName); 
OleDbConnection oledbConn = new OleDbConnection(connectionString); 
oledbConn.Open(); 

它提供了以下錯誤:

'D:\arrgh\arrgh\Uploads\countrylist.csv' is not a valid path. Make sure that the path name is spelled correctly and that you are connected to the server on which the file resides.

我驗證該文件在那裏。這裏發生了什麼?

回答

51

好吧,我挖了一個遠一點,似乎我的連接字符串是錯誤的。對於CSV文件,您不指定實際的文件名,而是指定它所屬的目錄,例如。

var fileName = string.Format("{0}{1}", AppDomain.CurrentDomain.BaseDirectory, "Uploads\\"); 
string connectionString = string.Format(@"Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}; Extended Properties=""text;HDR=YES;FMT=Delimited""", fileName); 
OleDbConnection oledbConn = new OleDbConnection(connectionString); 
oledbConn.Open(); 
var cmd = new OleDbCommand("SELECT * FROM [countrylist.csv]", oledbConn); 

然後在SelectCommand中指定文件名。這是多麼奇怪的做法。現在它爲我工作。

+6

另請注意,如果您使用Microsoft Jet OLEDB驅動程序讀取CSV文件,則無法讀取其文件名中具有多個點的任何CSV文件。也就是說,「filename.csv」將起作用,但「file.name.csv」不會。 – 2009-09-22 05:36:05

+0

並注意你想使用'sql = SELECT * FROM myfile.csv'(即沒有路徑的文件名)。您可以使用'csvFile = Right(csvPath,Len(csvPath) - InStrRev(csvPath,「\」))' – 2011-10-13 02:31:35

+4

@ TommyO'Dell或簡單地'Path.GetFileName(csvPath)' – 2013-04-05 19:59:01

2

爲路徑和文件名的組合方式是使用:

fullFilename = System.IO.Path.Combine(folderfilepath, Filename); 

在你的榜樣:

var fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Uploads\countrylist.csv"); 
+0

不,不工作,以及 – sean 2009-09-22 04:59:48

+1

@seanlinmt:這不是你的唯一的問題,但是這是非常中肯的意見。 *從不*作爲字符串進行路徑操作 - 始終使用'System.IO.Path'輔助函數。否則,總會有一個咬你的邊緣案例。 – 2009-09-22 05:44:40

0

如果d驅動器映射網絡驅動器,那麼你可能需要使用UNC路徑:

\\computerName\shareName\path\ 
1

我幾個星期前,有同樣的問題試圖做一些Office 2007的自動化和花費太多試圖修復它。

string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1;\""; 
4

我建議您使用CSV解析器而不是使用OLEDB數據提供程序。

搜索,你會發現許多(免費)的候選人。這裏是爲我工作的幾個:

A portable and efficient generic parser for flat files(最容易使用,IMO)
A Fast CSV Reader(易於使用,非常適合大型數據集)
FileHelpers庫(靈活,包括代碼生成器,一個學習的位曲線)

通常,這些將允許您指定CSV(分隔符,標題,文本限定符等)的屬性,並通過方法調用您的CSV轉儲到某種數據結構,如DataTable或列表<>。

如果您完全可以使用CSV工作,則需要查看CSV解析器。

+3

我用過「Fast CSV Reader」,很棒。 – 2009-09-22 05:45:20

+1

儘管我同意使用CSV解析器可能是最好的解決方案(請參閱我的答案,以瞭解實際內置於.NET Framework中的替代方案),但可能會出現使用Microsoft Jet OLEDB驅動程序的情況。一個有用的屬性是,它可以檢測CSV列的數據類型,在編寫代碼將CSV文件轉換爲其他格式(本例中爲DBF)時,我曾使用這些數據類型。 – 2009-09-22 05:47:17

+0

@Daniel - 對OLEDB供應商感興趣,我不知道。我不確定我是否想要使用此功能,但願意自己明確設置(並檢查)這些內容。謝謝(你的)信息。 – 2009-09-22 06:13:03

2

如果您只是想用C#讀取CSV文件,最簡單的方法就是使用Microsoft.VisualBasic.FileIO.TextFieldParser類。它實際上內置於.NET Framework中,而不是第三方擴展。

是的,它在Microsoft.VisualBasic.dll,但這並不意味着你不能從C#(或任何其他CLR語言)使用它。

下面是使用的例子,從MSDN documentation採取:

Using MyReader As New _ 
Microsoft.VisualBasic.FileIO.TextFieldParser("C:\testfile.txt") 
    MyReader.TextFieldType = FileIO.FieldType.Delimited 
    MyReader.SetDelimiters(",") 
    Dim currentRow As String() 
    While Not MyReader.EndOfData 
     Try 
     currentRow = MyReader.ReadFields() 
     Dim currentField As String 
     For Each currentField In currentRow 
      MsgBox(currentField) 
     Next 
     Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException 
     MsgBox("Line " & ex.Message & _ 
     "is not valid and will be skipped.") 
     End Try 
    End While 
End Using 

同樣,這個例子是VB.NET,但它是微不足道將其翻譯爲C#。