Skip to content

C# / .NET PDF ライブラリ — PDF Oxide

PDF Oxide は .NET 向けの最速 PDF ライブラリです。テキスト抽出はページ平均 0.8 ms、PyMuPDF の 5 倍、pypdf の 15 倍高速、3,830 件の PDF でパス率 100%。抽出・作成・編集をひとつのパッケージで扱えます。NativeAOT 対応、トリミング安全で、usingasync Task<T>CancellationToken、LINQ フレンドリーなコレクションを備えたイディオマティックな API。ライセンスは MIT / Apache-2.0 です。

インストール

dotnet add package PdfOxide

ターゲットフレームワーク: net8.0net10.0IsAotCompatible=trueIsTrimmable=true が有効化されています。

NuGet パッケージには Windows、macOS(Intel + Apple Silicon)、Linux(x64 + ARM64)向けのビルド済みネイティブライブラリが同梱されています。システム依存関係も Rust ツールチェインも不要です。

PDF を開く

using PdfOxide.Core;

using var doc = PdfDocument.Open("research-paper.pdf");
Console.WriteLine($"ページ数: {doc.PageCount}");
Console.WriteLine($"PDF バージョン: {doc.Version.Major}.{doc.Version.Minor}");

ストリームから:

using var stream = File.OpenRead("report.pdf");
using var doc = PdfDocument.Open(stream);

パスワード付き:

using var doc = PdfDocument.OpenWithPassword("secure.pdf", "user-password");

AES-256 (V=5, R=6) の PDF も完全にサポートしています。

Page API

v0.3.34 から PdfDocumentPages プロパティ(IReadOnlyList<PdfPage>)と int インデクサを提供するため、foreach による反復や LINQ が使えます。

using PdfOxide.Core;

using var doc = PdfDocument.Open("paper.pdf");

foreach (var page in doc.Pages)
{
    Console.WriteLine($"--- ページ {page.Index + 1} ---");
    Console.WriteLine(page.ExtractText());
}

// インデックスで直接アクセス
PdfPage first = doc[0];
string md = await first.ToMarkdownAsync();

PdfPage には同期・非同期のフルサーフェスが揃っています: ExtractText() / ExtractTextAsync()ToMarkdown()ToHtml()ToPlainText()ExtractWords()ExtractTextLines()ExtractTables()ExtractChars()ExtractImages()Search()

テキスト抽出

単一ページ

using var doc = PdfDocument.Open("report.pdf");

string text = doc.ExtractText(0);
Console.WriteLine(text);

全ページ

string allText = doc.ExtractAllText();

ページを手動で走査

for (int i = 0; i < doc.PageCount; i++)
{
    Console.WriteLine($"--- ページ {i + 1} ---");
    Console.WriteLine(doc.ExtractText(i));
}

非同期抽出

すべての抽出メソッドには *Async 版があり、Task<T> を返し、任意の CancellationToken を受け取ります。

using PdfOxide.Core;

using var doc = PdfDocument.Open("large.pdf");

string text = await doc.ExtractTextAsync(0);

// キャンセル付き fan-out
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var tasks = Enumerable.Range(0, doc.PageCount)
    .Select(i => doc.ExtractTextAsync(i, cts.Token));
string[] pages = await Task.WhenAll(tasks);

完全なパターンは 非同期ガイド を参照してください。

構造化抽出

var words = doc.ExtractWords(0);
foreach (var (text, x, y, w, h) in words)
{
    Console.WriteLine($"\"{text}\" @ ({x:F1}, {y:F1})");
}

// 矩形領域で
string regionText = doc.ExtractTextInRect(0, x: 50, y: 700, width: 200, height: 50);

var tables = doc.ExtractTables(0);
foreach (var (rows, cols) in tables)
{
    Console.WriteLine($"{rows}x{cols} のテーブル");
}

Markdown 変換

string markdown = doc.ToMarkdown(0);
string allMarkdown = doc.ToMarkdownAll();

HTML 変換

string html = doc.ToHtml(0);
string allHtml = doc.ToHtmlAll();

画像抽出

using PdfOxide.Core;

using var doc = PdfDocument.Open("brochure.pdf");
var images = doc.ExtractImages(0);

foreach (var img in images)
{
    Console.WriteLine($"{img.Width}x{img.Height} {img.Format} ({img.Colorspace}, {img.BitsPerComponent} bpc, {img.Data.Length} バイト)");
    File.WriteAllBytes($"image_{Array.IndexOf(images.ToArray(), img)}.{img.Format}", img.Data);
}

インデックスカラー PDF は自動的に RGB に展開されます(RGB・グレースケール・CMYK を基底色空間とする 1/2/4/8 bpc)。

検索

var results = doc.SearchAll("四半期売上");
foreach (var (page, text, x, y, w, h) in results)
{
    Console.WriteLine($"ページ {page}: \"{text}\" @ ({x}, {y})");
}

// 単一ページ・大文字小文字を区別
var pageResults = doc.SearchPage(0, "exact phrase", caseSensitive: true);

LINQ も自然に使えます。

var hitsByPage = doc.SearchAll("keyword")
    .GroupBy(r => r.Page)
    .OrderBy(g => g.Key);

foreach (var group in hitsByPage)
{
    Console.WriteLine($"ページ {group.Key}: ヒット {group.Count()} 件");
}

PDF の作成

using PdfOxide.Core;

// Markdown から
using (var pdf = Pdf.FromMarkdown("# 請求書\n\n合計: **$42.00**"))
{
    pdf.Save("invoice.pdf");
}

// HTML から
using (var pdf = Pdf.FromHtml("<h1>レポート</h1><p>作成日 2026-04-09</p>"))
{
    pdf.Save("report.pdf");
}

// プレーンテキストから
using (var pdf = Pdf.FromText("プレーンテキスト文書。\n\n2 段落目。"))
{
    pdf.Save("notes.pdf");
}

// 画像から
using (var pdf = Pdf.FromImage("scan.jpg"))
{
    pdf.Save("scan.pdf");
}

編集 — メタデータとフォーム

using PdfOxide.Core;

using var editor = DocumentEditor.Open("form.pdf");

// メタデータの読み取り
Console.WriteLine($"タイトル: {editor.Title}");
Console.WriteLine($"ページ数: {editor.PageCount}");

// メタデータの更新
editor.Title = "四半期レポート";
editor.Author = "財務チーム";
editor.Subject = "2026 Q1 業績";

// フォームフィールドの埋め込みとフラット化
editor.SetFormFieldValue("employee.name", "Jane Doe");
editor.SetFormFieldValue("employee.email", "jane@example.com");
editor.FlattenForms();

editor.Save("edited.pdf");
// または: await editor.SaveAsync("edited.pdf");

編集せずにフォームフィールドを読むだけの場合:

using var doc = PdfDocument.Open("form.pdf");
foreach (var f in doc.GetFormFields())
{
    Console.WriteLine($"{f.Name} ({f.FieldType}) = \"{f.Value}\"");
}

補足: 現在の .NET バインディングは、ドキュメントの開く/読み取り/変換/作成、画像抽出、フォームフィールドの読み取り・入力・フラット化、メタデータ編集に対応しています。ページ操作、注釈、レンダリング、署名は Rust コアと他のバインディングでは使用できますが、同等の .NET サーフェスは今後のリリースで追加予定です。

NativeAOT での発行

PDF Oxide の .NET バインディングは NativeAOT による発行に対応しています。

dotnet publish -c Release -r linux-x64 --self-contained -p:PublishAot=true

881 件の P/Invoke 宣言はすべて LibraryImport(ソース生成 P/Invoke)を使い、IsAotCompatible=trueIsTrimmable=true が設定されています。AOT コンパイルされたバイナリは使用部分だけをリンクし、ネイティブの Rust コアは同梱のプラットフォーム固有ライブラリにスタティックリンクされます。

プラグインと拡張

PdfOxide.Plugins パッケージ(PdfOxide と同時に配布)は、抽出したコンテンツを変換するプロセッサ(分類器、後処理、バリデータ)向けの拡張ポイントを提供します。拡張の作り方は プラグインガイド を参照してください。

エラー処理

すべてのメソッドは失敗時に型付き例外をスローします。

using PdfOxide.Core;

try
{
    using var doc = PdfDocument.Open("document.pdf");
    string text = doc.ExtractText(0);
}
catch (PdfOxideException ex)
{
    Console.Error.WriteLine($"PDF Oxide エラー: {ex.Message}");
}
catch (FileNotFoundException)
{
    Console.Error.WriteLine("ファイルが見つかりません");
}

次のステップ