【问题标题】:Processing excel files with data reader: ExecuteReader() buffers entire file使用数据阅读器处理 excel 文件:ExecuteReader() 缓冲整个文件
【发布时间】:2013-12-13 03:11:14
【问题描述】:

我在尝试使用数据阅读器处理大型 Excel 文件 (300mb+) 时遇到了一个特殊问题。 以下代码说明了我打开 excel 文件并遍历工作表“largesheet$”中的行的方式:

const string inputFilePath = @"C:\largefile.xlsx";
const string connectionString =
    "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES;\";Data Source=" +
    inputFilePath;

// Initialize connection
using (var connection = new OleDbConnection(connectionString))
{
    // Open connection
    connection.Open();

    // Configure command
    var command = new OleDbCommand("largesheet$", connection) {CommandType = CommandType.TableDirect};

    // Execute reader
    var reader = command.ExecuteReader(); // <-- Completely loads file/sheet into memory

    // Iterate results
    while (reader.HasRows)
    {
        // Read single row
        reader.Read();

        // ...
    }

    // Close connection
    connection.Close();
}

据我了解,这应该打开 excel 文件并在需要时使用 reader.Read() 语句加载每一行。
但是,似乎 ExecuteReader() 语句不仅仅返回一个 OleDbDataReader 实例。使用断点我注意到一条语句需要 30 多秒,并且 Windows 资源监视器表明在执行该语句期间分配的内存稳定增加。
指定 ExecuteReader() 方法的 CommandBehavior 参数(例如 SequentialAccess)无效。

我在这里做错了什么?是否有其他处理大型(excel)文件的方法?

注意:连接字符串的 IMEX 和 HDR 扩展属性是有意的。

编辑:经过一些理性思考,我认为如果不以一种或另一种方式缓冲它,就不可能处理 Excel 文件。由于 excel 文件基本上是压缩 XML 文件的美化集合,因此无法在不解压缩(并将其保存在 ram 中或临时保存到磁盘)的情况下处理工作表。
我能想到的唯一选择是使用Microsoft.Office.Interop.Excel。不过不确定OpenXML 是如何处理的。

【问题讨论】:

    标签: c# excel datareader


    【解决方案1】:

    来自MSDN:“当您调用 Command 对象的 Execute 方法之一时,将返回一个或多个命名表的所有行和列。” (在备注部分下)。所以这似乎是 ExecuteReader() 的默认行为。

    ExecuteReader(CommandBehavior) 可能会为您提供更多选择,尤其是当 CommandBehavior 设置为 SequentialAccess 时,尽管您需要处理字节级别的读取。

    【讨论】:

    • 正如我在问题中所说,使用 SequentialAccess 没有任何区别(我只尝试过与 TableDirect 结合使用)。我发现 ExecuteReader 将数据加载到内存中很奇怪,我认为数据读取器的优势之一是它们的敏捷性和性能。 .NET 框架是否提供更适合处理大型数据文件的替代方案?
    • 您是否考虑过使用 OpenXML (msdn.microsoft.com/en-us/library/office/bb448854.aspx) 来完成您的任务?这可能会给您更多的控制权,具体取决于您在加载数据后需要对其执行的操作。您可以使用 SDK 提供的类似 SAX 的读取来控制文件的读取方式。
    猜你喜欢
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多