Вступ

Коли вашому бізнесу потрібно індексувати великі партії рахунків, юридичних документів або експортованих листів, які надходять у вигляді стиснутих ZIP‑ або RAR‑файлів, традиційний підхід — розархівувати їх на диск, відкривати кожен файл окремим читачем і потім видаляти тимчасові файли. Така “подорож туди‑і‑знову” створює дорогий I/O, ускладнює очистку та перетворює роботу з вкладеними архівами на справжній кошмар.

GroupDocs.Parser для .NET усуває ці проблеми. Він дозволяє відкривати архів безпосередньо, перебирати кожен елемент і витягати сирий текст (і метадані) повністю в пам’яті. У цій статті ви дізнаєтеся, як:

  • Встановити пакет Parser через NuGet.
  • Отримати текст із плоского архіву за один прохід.
  • Рекурсивно обходити вкладені ZIP/RAR‑файли.
  • Застосувати найкращі налаштування для стійкої обробки.

Чому важливий парсинг архівів у пам’яті

Обробка архівів у пам’яті дає вам:

  • Нуль тимчасових файлів — нічого не залишає на диску.
  • Швидкість — уникає додаткових циклів читання/запису для кожного елементу.
  • Масштабованість — може працювати з великими архівами або потоками в хмарах, коли файлову систему недоступно.

Попередні вимоги

  • .NET 6.0 або новіша версія.
  • GroupDocs.Parser для .NET (остання версія) — див. тимчасову ліцензію для безкоштовної оцінки.
  • ZIP‑ або RAR‑архів, що містить підтримувані документи (PDF, DOCX, TXT тощо).

Встановлення

dotnet add package GroupDocs.Parser

Додайте потрібні простори імен:

using GroupDocs.Parser;
using GroupDocs.Parser.Data;
using System.Collections.Generic;
using System.IO;

Крок 1 – Відкриття архіву

Перший крок — створити екземпляр Parser, який вказує на файл архіву. GetContainer() повертає колекцію об’єктів ContainerItem — по одному для кожного елементу всередині архіву.

// Path to the archive you want to scan
string archivePath = "./SampleDocs/InvoicesArchive.zip";

using (Parser parser = new Parser(archivePath))
{
    // Retrieve every file (or nested archive) inside the container
    IEnumerable<ContainerItem> attachments = parser.GetContainer();

    if (attachments == null)
    {
        Console.WriteLine("Archive is empty or could not be read.");
        return;
    }

    // Hand off the collection to a helper that extracts text/metadata
    ExtractDataFromAttachments(attachments);
}

Що відбувається:

  • Конструктор Parser завантажує архів без його розпакування на диск.
  • GetContainer() лінивим чином читає каталог архіву і дає вам об’єкти ContainerItem, з якими можна працювати.

Крок 2 – Обробка кожного запису

ExtractDataFromAttachments обходить список ContainerItem, виводить базові метадані, виявляє вкладені архіви та витягує текст із звичайних документів. Метод повністю повторно використовуваний — викликайте його один раз для архіву верхнього рівня і знову для будь‑якого виявленого вкладеного архіву.

/// <summary>
/// Recursively extracts metadata and plain‑text from each item in an archive.
/// </summary>
static void ExtractDataFromAttachments(IEnumerable<ContainerItem> attachments)
{
    foreach (ContainerItem item in attachments)
    {
        // Print a quick line with file name and size (optional)
        Console.WriteLine($"File: {item.FilePath} | Size: {item.Metadata.Size} bytes");

        try
        {
            // Each ContainerItem can open its own Parser instance
            using (Parser itemParser = item.OpenParser())
            {
                if (itemParser == null)
                {
                    // The item is not a supported document – skip it
                    continue;
                }

                // Detect nested archives by extension (case‑insensitive)
                bool isArchive = item.FilePath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase) ||
                                 item.FilePath.EndsWith(".rar", StringComparison.OrdinalIgnoreCase);

                if (isArchive)
                {
                    // Recursively process the inner archive
                    IEnumerable<ContainerItem>? nested = itemParser.GetContainer();
                    if (nested != null)
                    {
                        ExtractDataFromAttachments(nested);
                    }
                }
                else
                {
                    // Regular document – extract its raw text
                    using (TextReader reader = itemParser.GetText())
                    {
                        string text = reader.ReadToEnd();
                        Console.WriteLine($"Extracted {text.Length} characters from {item.FilePath}");
                        // Here you could store `text` in a database, index it, etc.
                    }
                }
            }
        }
        catch (UnsupportedDocumentFormatException)
        {
            // The file type is not supported by GroupDocs.Parser – ignore gracefully
            Console.WriteLine($"Skipping unsupported format: {item.FilePath}");
        }
    }
}

Ключові моменти

  • Доступ до метаданих — item.Metadata дає вам ім’я файлу, розмір, дату створення тощо без читання вмісту файлу.
  • Рекурсивна обробка — той самий метод викликає сам себе, коли натрапляє на інший ZIP/RAR, забезпечуючи підтримку неограниченої глибини вкладеності.
  • Стійкість до помилок — UnsupportedDocumentFormatException ловиться, тому один «поганий» файл не зупинить всю роботу.

Крок 3 – Об’єднання всього разом

Нижче наведено мінімальну, готову до копіювання програму, що поєднує два попередні фрагменти. Вона демонструє повний сквозний процес: встановлення, відкриття, обробку та звітування.

using GroupDocs.Parser;
using GroupDocs.Parser.Data;
using System;
using System.Collections.Generic;
using System.IO;

class ArchiveTextExtractor
{
    static void Main(string[] args)
    {
        string archivePath = args.Length > 0 ? args[0] : "./SampleDocs/InvoicesArchive.zip";
        using (Parser parser = new Parser(archivePath))
        {
            IEnumerable<ContainerItem> attachments = parser.GetContainer();
            if (attachments == null)
            {
                Console.WriteLine("No items found in the archive.");
                return;
            }
            ExtractDataFromAttachments(attachments);
        }
    }

    static void ExtractDataFromAttachments(IEnumerable<ContainerItem> attachments)
    {
        foreach (ContainerItem item in attachments)
        {
            Console.WriteLine($"File: {item.FilePath} | Size: {item.Metadata.Size} bytes");
            try
            {
                using (Parser itemParser = item.OpenParser())
                {
                    if (itemParser == null) continue;

                    bool isArchive = item.FilePath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase) ||
                                     item.FilePath.EndsWith(".rar", StringComparison.OrdinalIgnoreCase);

                    if (isArchive)
                    {
                        var nested = itemParser.GetContainer();
                        if (nested != null) ExtractDataFromAttachments(nested);
                    }
                    else
                    {
                        using (TextReader reader = itemParser.GetText())
                        {
                            string text = reader.ReadToEnd();
                            Console.WriteLine($"Extracted {text.Length} chars from {item.FilePath}");
                        }
                    }
                }
            }
            catch (UnsupportedDocumentFormatException)
            {
                Console.WriteLine($"Unsupported format: {item.FilePath}");
            }
        }
    }
}

Запустіть програму, вказавши шлях до вашого архіву:

dotnet run -- ./Data/LegalDocs.zip

Кращі практики та поради

  • Обмежте параметри парсингу — за замовчуванням Parser витягує весь підтримуваний контент. Якщо потрібен лише текст, уникайте викликів важких методів типу GetImages().
  • Великі архіви — обробляйте елементи послідовно, як показано; не завантажуйте весь текст одразу в пам’ять.
  • Продуктивність — пропускайте вкладені архіви, які не потрібні, перевіряючи розширення файлу перед рекурсією.
  • Обробка помилок — завжди ловіть UnsupportedDocumentFormatException; у корпоративних архівах часто є бінарники, які парсер не може читати.

Висновок

GroupDocs.Parser для .NET надає чистий, пам’яттю‑орієнтований спосіб читати будь‑який документ всередині ZIP‑ або RAR‑архівів, незалежно від глибини їх вкладеності. За кілька рядків коду можна замінити складні конвеєри «розпакувати + парсити», скоротити навантаження I/O та створити надійні сервіси інджесту документів.

Наступні кроки

Додаткові ресурси