はじめに
ビジネスで大量の請求書、法的文書、またはメールエクスポートが圧縮された ZIP や RAR ファイルとして届く場合、従来の手法はそれらをディスクへ解凍し、個々のリーダーでファイルを開き、最後に一時ファイルを削除するというものです。この往復処理は高コストな I/O を生み、クリーンアップを複雑にし、ネストされたアーカイブの取り扱いを悪夢のようにします。
GroupDocs.Parser for .NET はこれらの課題を解消します。アーカイブを直接開き、すべてのエントリを列挙し、生テキスト(およびメタデータ)を完全にメモリ上で抽出できます。本記事では以下を学びます。
- Parser NuGet パッケージをインストールする。
- フラットなアーカイブからテキストを一度のパスで取得する。
- ネストされた ZIP/RAR ファイルを再帰的に走査する。
- 堅牢な処理のためのベストプラクティス設定を適用する。
メモリ内アーカイブ解析が重要な理由
- 一時ファイルゼロ – ディスクが散らからず、残りファイルもない。
- 高速 – 各エントリの余分な読み書きサイクルを回避する。
- スケーラビリティ – ファイルシステムが利用できない大規模アーカイブやクラウドストリームを処理できる。
前提条件
- .NET 6.0 以降。
- GroupDocs.Parser for .NET(最新バージョン) – 無料評価には 一時ライセンス をご参照ください。
- サポートされているドキュメント(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() はアーカイブ内のエントリごとに 1 つずつ 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を捕捉することで、1つの不正ファイルが全体の実行を中止しません。
ステップ 3 – すべてをまとめる
以下は上記 2 つのスニペットを組み合わせた最小限のコピー&ペースト可能なプログラムです。インストール、オープン、処理、レポートというエンドツーエンドのフローを示しています。
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+parse パイプラインを置き換え、I/O オーバーヘッドを削減し、信頼性の高い文書取り込みサービスを構築できます。
次のステップ