Wstęp

Kiedy Twoja firma musi przetworzyć duże partie faktur, dokumentów prawnych lub eksportów e‑maili, które przychodzą jako skompresowane pliki ZIP lub RAR, tradycyjne podejście polega na rozpakowaniu ich na dysk, otwarciu każdego pliku osobnym czytnikiem i późniejszym usunięciu plików tymczasowych. Ten obieg dodaje kosztowne operacje I/O, komplikuje sprzątanie i sprawia, że obsługa zagnieżdżonych archiwów staje się koszmarem.

GroupDocs.Parser for .NET eliminuje te problemy. Umożliwia otwarcie archiwum bezpośrednio, wyliczenie każdego wpisu oraz wyodrębnienie surowego tekstu (i metadanych) w całości w pamięci. W tym artykule dowiesz się, jak:

  • Zainstalować pakiet NuGet Parser.
  • Pobierać tekst z płaskiego archiwum w jednym przebiegu.
  • Rekurencyjnie przechodzić zagnieżdżone pliki ZIP/RAR.
  • Zastosować zalecane ustawienia dla solidnego przetwarzania.

Dlaczego parsowanie archiwów w pamięci ma znaczenie

Przetwarzanie archiwów w pamięci daje Ci:

  • Zero plików tymczasowych – brak bałaganu na dysku, brak pozostawionych plików.
  • Szybkość – uniknięcie dodatkowych cykli odczytu/zapisu dla każdego wpisu.
  • Skalowalność – obsługa dużych archiwów lub strumieni w chmurze, gdzie system plików może nie być dostępny.

Wymagania wstępne

  • .NET 6.0 lub nowszy.
  • GroupDocs.Parser for .NET (najświeższa wersja) – zobacz tymczasową licencję w celu darmowej oceny.
  • Archiwum ZIP lub RAR zawierające obsługiwane dokumenty (PDF, DOCX, TXT itp.).

Instalacja

dotnet add package GroupDocs.Parser

Dodaj wymagane przestrzenie nazw:

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

Krok 1 – Otwórz archiwum

Pierwszym krokiem jest utworzenie instancji Parser, która wskazuje na plik archiwum. GetContainer() zwraca kolekcję obiektów ContainerItem – po jednym dla każdego wpisu w archiwum.

// 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);
}

Co się dzieje:

  • Konstruktor Parser ładuje archiwum bez rozpakowywania go na dysk.
  • GetContainer() leniwie odczytuje katalog archiwum i zwraca obiekty ContainerItem, z którymi możesz pracować.

Krok 2 – Przetwórz każdy wpis

ExtractDataFromAttachments przegląda listę ContainerItem, wyświetla podstawowe metadane, wykrywa zagnieżdżone archiwa i wyodrębnia tekst z zwykłych dokumentów. Metoda jest w pełni wielokrotnego użytku – wywołaj ją raz dla archiwum głównego i ponownie dla każdego zagnieżdżonego archiwum, które odkryjesz.

/// <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}");
        }
    }
}

Kluczowe punkty

  • Dostęp do metadanychitem.Metadata dostarcza nazwę pliku, rozmiar, datę utworzenia itp., bez odczytywania zawartości pliku.
  • Obsługa rekurencyjna – Ta sama metoda wywołuje siebie, gdy napotka kolejny ZIP/RAR, co zapewnia nieograniczone wsparcie dla zagnieżdżenia.
  • Odporność na błędyUnsupportedDocumentFormatException jest przechwytywany, więc pojedynczy wadliwy plik nie przerwie całego działania.

Krok 3 – Złożenie wszystkiego razem

Poniżej znajduje się minimalny, gotowy do skopiowania program, który łączy dwa powyższe fragmenty. Demonstruje pełny przepływ od instalacji, przez otwarcie, przetworzenie, po raportowanie.

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}");
            }
        }
    }
}

Uruchom program, podając ścieżkę do swojego archiwum:

dotnet run -- ./Data/LegalDocs.zip

Najlepsze praktyki i wskazówki

  • Ogranicz opcje parsowania – Domyślnie Parser wyodrębnia wszystkie obsługiwane treści. Jeśli potrzebujesz jedynie tekstu, nie wywołuj dodatkowych, ciężkich metod takich jak GetImages().
  • Duże archiwa – Przetwarzaj pozycje kolejno, jak pokazano powyżej; unikaj ładowania wszystkich tekstów do pamięci jednocześnie.
  • Wydajność – Pomijaj niepotrzebne zagnieżdżone archiwa, sprawdzając rozszerzenie pliku przed rekurencją.
  • Obsługa błędów – Zawsze przechwytuj UnsupportedDocumentFormatException; w wielu firmowych archiwach znajdują się pliki binarne, których parser nie potrafi odczytać.

Podsumowanie

GroupDocs.Parser for .NET zapewnia czysty, pamięciowy sposób na odczyt każdego dokumentu wewnątrz archiwów ZIP lub RAR, niezależnie od tego, jak głęboko są zagnieżdżone. Kilka linijek kodu pozwala zastąpić skomplikowane potoki rozpakowywanie + parsowanie, zredukować narzut I/O i zbudować niezawodne usługi pobierania dokumentów.

Kolejne kroki

Dodatkowe zasoby