14

我一直在使用 Microsoft.Jet.OLEDB.4.0 和 Microsoft.ACE.OLEDB.12.0 来读取 .csv、.xls 和 .xlsx 文件。

我刚刚发现本机 64 位模式不支持这些技术!

我有两个问题:

  1. 在 64 位模式下以编程方式读取 .csv、.xls 和 .xlsx 文件的支持方式是什么。我只是无法在任何地方找到答案。

  2. 如果我无法读取所有三种文件类型,在 64 位环境中读取 .csv 文件的最佳方式是什么?

笔记:

  • 我正在使用 .NET (3.5p1)
  • 这是一个收缩包装应用程序;再分配是一个关键因素。

更新:

我可以使用 CorFlags 强制应用程序以 32 位模式运行,这可行,但不可取。

4

7 回答 7

8

这是关于如何处理已弃用的 MDAC的讨论。恐怕答案不是很满意……

这些新的或转换后的 Jet 应用程序可以继续使用 Jet,目的是使用 Microsoft Office 2003 和更早的文件(.mdb 和 .xls)进行非主要数据存储。但是,对于这些应用程序,您应该计划从 Jet 迁移到 2007 Office System Driver。您可以下载 2007 Office System 驱动程序,它允许您读取和写入 Office 2003(.mdb 和 .xls)或 Office 2007(*.accdb、*.xlsm、*.xlsx 和*.xlsb) 文件格式。重要请阅读 2007 Office System 最终用户许可协议以了解具体的使用限制。

注意:SQL Server 应用程序还可以通过 2007 Office System 驱动程序从 SQL Server 异构数据连接和集成服务功能访问 2007 Office System 和更早版本的文件。此外,64 位 SQL Server 应用程序可以通过在 64 位 Windows 上使用 32 位 SQL Server 集成服务 (SSIS) 访问 32 位 Jet 和 2007 Office System 文件。

于 2009-05-14T00:30:51.943 回答
4

主要问题是 Jet DBMS 是一个 32 位库,它会被加载到调用进程中,因此您永远无法在 64 位模式下直接从应用程序中使用 Jet。正如 Tim 提到的,您可以编写自己的 csv 解析器,但由于这是一个收缩包装应用程序,您需要能够处理更广泛格式的东西。幸运的是,有多种方法可以使用 32 位应用程序,因此您仍然可以通过技巧使用 Jet。

我会编写一个标记为仅在 32 位模式下运行的小 exe。此 exe 将采用要读取的文件名和要写入的临时文件名的命令行参数。我会使用 Jet 加载 csv/xls,然后将数据放入数组数组中,然后使用 xml 序列化程序将数据写入临时文件。

然后,当我需要加载/转换 csv/xls 文件时,我会执行以下操作:

object[][] ConvertFile(string csvOrXlsFile)
{
    var output = System.IO.Path.GetTempFileName();
    try
    {
        var startinfo = new System.Diagnostics.ProcessStartInfo("convert.exe",
            string.Format("\"{0}\" \"{1}\"", csvOrXlsFile, output));

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo = startinfo;

        proc.Start();
        proc.WaitForExit();

        var serializer = new System.Xml.Serialization.XmlSerializer(typeof(object[][]));
        using (var reader = System.IO.File.OpenText(output))
            return (object[][])serializer.Deserialize(reader);
    }
    finally
    {
        if (System.IO.File.Exists(output))
            System.IO.File.Delete(output);
    }
}
于 2009-05-17T08:00:43.807 回答
4

您可以尝试使用FileHelpers库进行平面文件解析。效果非常好。

于 2009-05-18T17:45:00.953 回答
4

SpreadsheetGear for .NET可以读取和写入 .csv / .xls / .xlsx 工作簿(以及更多)并支持 64 位 .NET 2.0+。SpreadsheetGear 可以通过您的收缩包装应用程序免费分发。

您没有指定您的应用程序是 WinForms 还是 ASP.NET,但 SpreadsheetGear 可以使用其中任何一个。您可以在此处查看实时 ASP.NET (C# & VB) 示例,在此处了解 WinForms 示例并在此处下载免费试用版如果您想自己尝试的话。

免责声明:我拥有 SpreadsheetGear LLC

于 2009-07-10T15:15:45.123 回答
3

您可以使用 Microsoft Access Database Engine 2010 Redistributable来读写 csv、xls 访问等。每个驱动程序都有 32 位和 64 位版本。

于 2010-01-15T18:57:34.523 回答
3

对于可能遇到此问题的任何人来说,这更像是一篇信息性帖子(对我自己来说,以防我将来遇到同样的问题并且不记得解决方案:-))这有点晦涩,但给我带来了几个小时的压力,所以也许它会帮助其他人......对不起,如果这是重复的(找不到它)或不推荐使用(有些人没有最新和最伟大的奢侈品)。

如果您尝试使用 Jet 4.0 在基于 x64 的服务器上访问 MS Excel 文档(或其他数据文件),您会发现不支持这种组合。

唯一的解决方案是允许 IIS 在 Windows 64 上运行 32 位应用程序并安装受支持的数据库提供程序。

您需要安装驱动程序,用于 ODBC (MSDASQL) 的 64 位 OLEDB Provider 作为桥梁:“Microsoft OLE DB Provider for ODBC (MSDASQL) 是一种技术,它允许基于 OLEDB 和 ADO 构建的应用程序 (内部使用 OLEDB)通过 ODBC 驱动程序访问数据源。MSDASQL 是连接到 ODBC 而不是数据库的 OLEDB 提供程序。MSDASQL 随 Windows 操作系统一起提供,Windows Server 2008 和 Windows Vista SP1 是第一个 Windows 版本包括该技术的 64 位版本。” 在此处下载:http: //www.microsoft.com/downloads/details.aspx?FamilyID=000364db-5e8b-44a8-b9be- ca44d18b059b&displaylang=en

这一切都很好,但我遇到了两件事让我摸不着头脑(并强调):1)您需要在 IIS Web 服务扩展中允许 32 位 ASP.Net - 阅读“” http://www.textcontrol .com/blog/permalink/2006082101 ""有关启用 32 位应用程序和 IIS Web 服务扩展设置的说明。2) 如果您在 IIS x64 下使用任何注册表项,将在注册表中添加一个新节点 - Wow6432Node - 您需要将在 x64 下使用的任何相关键移动/复制到其中。即我们有一个存储在 HCLM\Software\CustomKey 中的数据密钥,当启用 32 位时该密钥不再可用。我们在 Wow6432Node 下重新创建了密钥,一切都很好。

于 2010-05-06T11:39:56.320 回答
1

实际上,我认为 Linq 是您最好的解决方案。

就像是....

IEnumerable<MyObj> ObjList = GetObjList(yourCSVFileNAme);

var qry = from o in ObjList
          where o.MyField == Something
          select o;

你的 GetObjList 方法看起来像

Public IEnumerable<MyObj> GetObjList(string filename)
{
  // Obvioulsly you would have some actual validation and error handling
  foreach(string line in File.ReadAllLines(filename))
  {
    string[] fields = line.Split(new char[]{','});
    MyObj obj = new MyObj();
    obj.Field = fields[0];
    obj.AnotherField = int32.Parse(fields[1]);
    yield return obj;
  }
}
于 2009-05-14T00:44:21.377 回答