مقدمه

وقتی کسب‌وکار شما نیاز دارد تا حجم زیادی از فاکتورها، اسناد قانونی یا خروجی‌های ایمیل که به‌صورت فایل‌های فشرده ZIP یا RAR می‌آیند را پردازش کند، روش سنتی این است که آن‌ها را روی دیسک استخراج کنید، هر فایل را با یک خواننده جداگانه باز کنید و سپس فایل‌های موقت را حذف کنید. این مسیر دور‑دور هزینه‌های I/O را افزایش می‌دهد، پاک‌سازی را پیچیده می‌کند و کار با آرشیوهای تو در تو را تبدیل به کابوسی می‌کند.

GroupDocs.Parser for .NET این مشکلات را از بین می‌برد. این کتابخانه به شما امکان می‌دهد آرشیو را به‌صورت مستقیم باز کنید، هر ورودی را فهرست کنید و متن خام (و متادیتا) را به‌طور کامل در حافظه استخراج کنید. در این مقاله خواهید آموخت چگونه:

  • بسته NuGet Parser را نصب کنید.
  • متن را از یک آرشیو صاف در یک عبور استخراج کنید.
  • به‌صورت بازگشتی فایل‌های ZIP/RAR تو در تو را پیمایش کنید.
  • تنظیمات بهترین روش‌ها را برای پردازش مقاوم اعمال کنید.

چرا تجزیه‌وتحلیل آرشیو در حافظه مهم است

پردازش آرشیوها در حافظه به شما این مزایا را می‌دهد:

  • بدون فایل‌های موقت – هیچ شلوغی دیسکی، هیچ فایل باقی‌مانده‌ای نیست.
  • سرعت – از چرخه خواندن/نوشتن اضافی برای هر ورودی جلوگیری می‌کنید.
  • قابلیت مقیاس‌پذیری – می‌توانید آرشیوهای بزرگ یا جریان‌های ابری را که ممکن است سیستم فایل در دسترس نباشد، پردازش کنید.

پیش‌نیازها

  • .NET 6.0 یا بالاتر.
  • GroupDocs.Parser for .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() به‌صورت تنبل (lazy) فهرست آرشیو را می‌خواند و اشیاء 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 for .NET روشی تمیز و در‑حافظه برای خواندن هر سند داخل آرشیوهای ZIP یا RAR فراهم می‌کند، حتی اگر به‌صورت عمیق تو در تو باشند. با تنها چند خط کد می‌توانید خطوط پیچیده استخراج‑ unzip‑plus‑parse را جایگزین کنید، هزینه I/O را کاهش دهید و سرویس‌های ورودی اسناد قابل اطمینان بسازید.

گام‌های بعدی

  • ویژگی‌های document comparison یا metadata extraction را بررسی کنید.
  • یاد بگیرید چگونه با همان API تصاویر را از فایل‌های آرشیو استخراج کنید.
  • متن استخراج‌شده را به یک ایندکس جستجو یا خط لوله هوش مصنوعی متصل کنید.

منابع تکمیلی