C#读取CSV文件时出现“不是有效路径”的错误提示。

28

我似乎无法使用以下连接字符串读取一个 .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' 不是有效的路径。请确保路径名拼写正确,且您已连接到文件所在的服务器。

我确认文件已经存在。这里发生了什么?

7个回答

64

好的,我深入研究了一下,似乎我的连接字符串是错误的。对于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”将无法读取。 - Daniel Pryden
请注意,您要使用 sql = SELECT * FROM myfile.csv(即没有路径的文件名)。您可以使用 csvFile = Right(csvPath, Len(csvPath) - InStrRev(csvPath, "\")) 从完整路径中提取文件名。 - Tommy O'Dell
4
@TommyO'Dell 或者简单地说 Path.GetFileName(csvPath) 的意思是获取一个文件路径的文件名,不包括路径信息。 - Josh M.
完美运行!谢谢! - Stefan S
正是我所缺少的。谢谢! - Atta H.

4
我建议您使用CSV解析器而不是使用OLEDB数据提供程序。
搜索一下,您会找到许多(免费)候选者。以下是一些对我有用的: 适用于扁平文件的便携式高效通用解析器(在我看来最容易使用)
快速CSV阅读器(易于使用,非常适合大型数据集)
FileHelpers库(灵活,包括代码生成器,但需要一定的学习曲线)
通常,这些解析器将允许您指定CSV的属性(分隔符、标题、文本限定符等),并通过一个方法调用将CSV转储到某种数据结构中,如DataTable或List<>。
如果您将与CSV有任何工作,那么值得检查一下CSV解析器。

3
我用过"Fast CSV Reader",它很好用。 - Ty.
1
虽然我同意使用CSV解析器可能是最好的解决方案(请参见我的答案,其中提供了一种实际上已经内置在.NET Framework中的替代方法),但使用Microsoft Jet OLEDB驱动程序可能有用。一个有用的属性是它可以检测CSV列的数据类型,我过去在编写将CSV文件转换为不同格式(在我的情况下是DBF)的代码时使用过这个属性。 - Daniel Pryden
@Daniel - 有关OLEDB提供程序的信息很有趣,我之前并不知道。虽然如此,我不确定是否想要使用这个功能,因为我更喜欢自己明确设置(和检查)这些内容。感谢您提供的信息。 - Jay Riggs

2
合并路径和文件名的方法是使用:
fullFilename = System.IO.Path.Combine(folderfilepath, Filename);

在你的例子中:

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

1
@seanlinmt:这不是你唯一的问题,但这是非常明智的建议。永远不要将路径操作作为字符串处理 - 总是使用 System.IO.Path 帮助函数。否则,总会有那么一个边缘情况会咬你一口。 - Daniel Pryden

2
如果您只是想使用C#读取CSV文件,最简单的方法是使用Microsoft.VisualBasic.FileIO.TextFieldParser类。 它实际上内置在.NET Framework中,而不是作为第三方扩展。
是的,它在Microsoft.VisualBasic.dll中,但这并不意味着您不能从C#(或任何其他CLR语言)使用它。
以下是一个使用示例,摘自MSDN文档
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#非常容易。

1

几周前我也遇到了同样的问题,试图进行一些 Office 2007 自动化并花费了太多时间尝试修复它。

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

0
如果D盘是映射的网络驱动器,则可能需要使用UNC路径:
\\computerName\shareName\path\

-1
尝试这个,一个快速的CSV阅读器,高效的CSV解析器。

CsvReader


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接