介绍

当您的业务需要摄取大量的发票、法律文件或以压缩 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 开销,并构建可靠的文档摄取服务。

后续步骤

其他资源