מבוא

כאשר העסק שלך צריך לצרוך כמויות גדולות של חשבוניות, מסמכי משפט או ייצוא של אימיילים שמגיעים כקבצי ZIP או RAR דחוסים, הגישה המסורתית היא לפרק אותם לדיסק, לפתוח כל קובץ עם קורא נפרד, ואז למחוק את הקבצים הזמניים. הסיבוב הזה מוסיף I/O יקר, מסבך את הניקוי וממיר טיפול בארכיונים מקוננים לסיוט.

GroupDocs.Parser עבור .NET מסיר את נקודות הכאב האלה. הוא מאפשר לך לפתוח ארכיון ישירות, למנות כל פריט, ולחלץ טקסט גולמי (ומטא‑נתונים) באופן מוחלט בזיכרון. במאמר זה תלמד כיצד:

  • להתקין את חבילת ה‑NuGet של Parser.
  • לחלץ טקסט מארכיון שטוח בקלף אחד.
  • לעבור בצורה רקורסיבית על קבצי ZIP/RAR מקוננים.
  • ליישם הגדרות מיטב‑הפרקטיקה לעיבוד יציב.

למה עיבוד ארכיונים בזיכרון חשוב

עיבוד ארכיונים בזיכרון נותן לך:

  • אפס קבצים זמניים – אין עומס על הדיסק, אין קבצים שלישיים.
  • מהירות – ניתוח קריאה/כתיבה מיותרת לכל פריט.
  • סקלאביליות – טיפול בארכיונים גדולים או בזרמי ענן שבהם מערכת קבצים עשויה לא להיות זמינה.

דרישות מוקדמות

  • .NET 6.0 או גרסה מאוחרת יותר.
  • GroupDocs.Parser עבור .NET (הגרסה העדכנית) – ראה את ה‑רישיון זמני להערכה חינמית.
  • ארכיון ZIP או RAR המכיל מסמכים נתמכים (PDF, DOCX, TXT וכדומה).

התקנה

dotnet add package GroupDocs.Parser

הוסף את ה‑namespaces הנדרשים:

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; ארכיונים ארגוניים רבים מכילים קבצים בינאריים שה-parser אינו יכול לקרוא.

סיכום

GroupDocs.Parser עבור .NET מספק דרך נקייה, בזיכרון, לקרוא כל מסמך בתוך ארכיוני ZIP או RAR, בלי קשר לעומק הקידוד שלהם. עם כמה שורות קוד בלבד ניתן להחליף צינורות מורכבים של unzip‑plus‑parse, לצמצם עומסי I/O ולבנות שירותי לקיחת מסמכים אמינים.

צעדים הבאים

משאבים נוספים