介紹

當您的業務需要處理大量以 ZIP 或 RAR 壓縮檔形式傳送的發票、法律文件或電子郵件匯出檔時,傳統的做法是先將壓縮檔解壓至磁碟,然後使用單獨的讀取器打開每個檔案,最後再刪除暫存檔。這樣的往返會產生昂貴的 I/O、使清理工作變得複雜,且處理巢狀壓縮檔更是噩夢。

GroupDocs.Parser for .NET 消除這些痛點。它讓您 直接開啟壓縮檔、列舉每個條目,並 在記憶體中完整提取純文字(及中繼資料)。在本文中,您將學會:

  • 安裝 Parser NuGet 套件。
  • 在一次遍歷中從平面壓縮檔取得文字。
  • 遞迴遍歷巢狀 ZIP/RAR 檔案。
  • 套用最佳實務設定以取得穩定的處理效能。

為何記憶體內部的壓縮檔解析很重要

在記憶體中處理壓縮檔可為您帶來:

  • 零暫存檔——不會留下磁碟雜訊,也不會有遺留檔案。
  • 速度——避免對每個條目進行額外的讀寫循環。
  • 可擴充性——能處理大型壓縮檔或雲端串流,即使檔案系統不可用。

前置條件

  • .NET 6.0 或更新版本。
  • GroupDocs.Parser for .NET(最新版本)——參見 temporary license 以取得免費評估版。
  • 包含支援文件(PDF、DOCX、TXT 等)的 ZIP 或 RAR 壓縮檔。

安裝

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 for .NET 提供了一種乾淨的記憶體內部方式,能讀取 ZIP 或 RAR 壓縮檔內的每份文件,無論巢狀層級多深。只需幾行程式碼,即可取代複雜的「解壓+解析」流程,減少 I/O 開銷,並打造可靠的文件匯入服務。

後續步驟

其他資源