Как обрабатывать очень большие файлы .xlsx с C# - PullRequest
2 голосов
/ 19 января 2020

Ситуация, которую мне нужно решить :

У моего клиента есть несколько очень больших файлов .xlsx, которые напоминают таблицу базы данных (каждая строка - это запись, столбцы - это поля)

Мне нужно помочь им обработать эти файлы (поиск, фильтр и т. Д. c).

В целом я имею в виду, что у самой маленькой из них 1 миллион записей.


Что я пробовал:

  • Sheet JS и NPOI: обе библиотеки отвечают только простым «слишком большим файлом».
  • EPPlus: может считывать файлы до нескольких сотен K записей, но когда сталкиваюсь с реальным файлом, это просто дает мне System.OverflowException, я думаю, что это в основном нехватка памяти, потому что файл xlsx 200 МБ уже занял у меня 4 ГБ памяти читать.
  • Я не пробовал Microsoft OleDB, но я бы предпочел этого избежать, поскольку я не хочу покупать Microsoft Office просто для работы.

Из-за конфиденциальности я не могу предоставить общий доступ к реальному файлу, но вы можете легко создать аналогичную структуру с 60 столбцами (первое имя e, фамилия, dob, et c) и около 1 млн записей.

Вопрос будет решен , как только вы сможете прочитать файл .xlsx с этими критериями, удалите половина записей затем записывается в другое место, не сталкиваясь с проблемой памяти.

  • Время - не слишком большая проблема. Пользователь готов подождать час или 2, чтобы получить результат, если это необходимо.
  • Кажется, проблема памяти сейчас. Это личный запрос, и клиентский компьютер является ноутбуком с 8 ГБ ОЗУ.
  • csv не вариант здесь. У моего клиента есть входные данные .xlsx и требуется вывод .xlsx.
  • Выбор языка предпочтительно JS, C# для Python, так как я уже знаю, как создать исполняемый файл с ними (ну, не могу сказать, бухгалтер для изучения терминала, не так ли?).

Было бы замечательно, если бы был способ медленно читать небольшие порции данных из файла строка за строкой, но решения, которые я нашел читать только весь файл одновременно.

1 Ответ

3 голосов
/ 19 января 2020

Для чтения Excel файла я бы рекомендовал ExcelDataReader . Это очень хорошо с чтением больших файлов. Я лично пытался 500k-1M:

using (var stream = File.Open("C:\\temp\\input.xlsx", FileMode.Open, FileAccess.Read))
{
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        while (reader.Read())
        {
            for (var i = 0; i < reader.FieldCount; i++)
            {
                var value = reader.GetValue(i)?.ToString();
            }
        }
    }
}

Записать данные таким же эффективным способом более сложно. Я закончил с созданием моей собственной библиотеки SwiftExcel , которая чрезвычайно быстра и эффективна (есть диаграмма производительности по сравнению с другими библиотеками Nuget, включая EPPlus), поскольку она не использует XML -сериализацию и записывает данные непосредственно в файл:

using (var ew = new ExcelWriter("C:\\temp\\test.xlsx"))
{
    for (var row = 1; row <= 100; row++)
    {
        for (var col = 1; col <= 10; col++)
        {
            ew.Write($"row:{row}-col:{col}", col, row);
        }
    }
}
...