Exis.PdfEditor logo

.NET 用 PDF 検索・置換 SDK

C# で PDF ファイル内のテキストをプログラムで検索・置換。コンテンツストリームの直接編集 — DOCXへの変換不要、外部依存なし、データ損失なし。

.NET CLI dotnet add package Exis.PdfEditor

PM Console Install-Package Exis.PdfEditor

Exis.PdfEditorを選ぶ理由

他のライブラリの動作方法

ほとんどの.NET PDFライブラリ — IronPDF、Spire.PDF、Aspose、Syncfusion — はPDFを中間形式に変換、テキストを墨消して新しいテキストを上に描画、またはページをゼロから再構築してテキストを置換します。

このアプローチは以下を破壊します:

  • フォームフィールドとチェックボックスの値
  • デジタル署名
  • テキストの間隔とカーニング
  • ページレイアウトと配置
  • ブックマークとリンク先

Exis.PdfEditorの動作方法

Exis.PdfEditorはPDFコンテンツストリームをバイトレベルで直接解析します。実際のPDFオペレータ内のテキストを特定し、対象の文字列オペランドのみを変更し、PDFインクリメンタル更新で書き戻します。

変更されない部分はバイト単位で同一のままです:

  • フォームフィールドとAcroForms:そのまま
  • 未変更ページのデジタル署名:保持
  • テキストの間隔とカーニング:保持
  • ページレイアウトと構造:保持
  • ブックマーク、注釈、埋め込みファイル:保持

他のライブラリ

PDF
中間形式に変換
変更
PDFに再変換
出力(損傷あり)

Exis.PdfEditor

PDF
コンテンツストリームを解析
テキストオペランドを置換
インクリメンタル更新
出力(置換テキスト以外同一)

Code Samples

PDF内のテキストを置換 — 3行のコード

using Exis.PdfEditor;
using Exis.PdfEditor.Licensing;

ExisLicense.Initialize();  // Free 14-day trial - no key needed

var result = PdfFindReplace.Execute(
    "contract.pdf",
    "contract-updated.pdf",
    "Acme Corporation",
    "Globex Industries");

Console.WriteLine($"Replaced {result.TotalReplacements} occurrences " +
                  $"across {result.PagesModified} pages.");

1回のパスで複数の置換

var pairs = new[]
{
    new FindReplacePair("2025", "2026"),
    new FindReplacePair("Draft", "Final"),
    new FindReplacePair("CONFIDENTIAL", "PUBLIC"),
};

var result = PdfFindReplace.Execute(
    "report.pdf",
    "report-final.pdf",
    pairs);

正規表現によるパターンベースの置換

var options = new PdfFindReplaceOptions { UseRegex = true };

// Replace all US phone numbers with a placeholder
var result = PdfFindReplace.Execute(
    "document.pdf",
    "redacted.pdf",
    @"\(\d{3}\)\s?\d{3}-\d{4}",
    "[PHONE REDACTED]",
    options);

サブスクリプションを有効化

// Purchase at officefindreplace.com/Home/pdf-find-replace-csharp - $499/developer/year
ExisLicense.Initialize("XXXX-XXXX-XXXX-XXXX");

// Unlimited pages, no restrictions, no console messages
var result = PdfFindReplace.Execute("large-doc.pdf", "output.pdf", "old", "new");

Text Fitting Options

var options = new PdfFindReplaceOptions
{
    CaseSensitive = true,
    WholeWordOnly = false,
    UseRegex = false,
    UseIncrementalUpdate = true,
    TextFitting = TextFittingMode.Adaptive,  // Best quality text fitting
    MinHorizontalScale = 70,                 // Minimum Tz percentage (50-100)
    MaxFontSizeReduction = 1.5               // Max font size reduction in points
};

var result = PdfFindReplace.Execute(
    "contract.pdf", "updated.pdf",
    "Short Name", "A Much Longer Replacement Name That Needs Fitting",
    options);

Font Color & Highlight

// Color replacement text and add a highlight background
var result = PdfFindReplace.Execute(
    "input.pdf", "output.pdf",
    "old text", "new text",
    new PdfFindReplaceOptions
    {
        ReplacementTextColor = PdfColor.Red,         // Font color of replaced text
        ReplacementHighlightColor = PdfColor.Yellow   // Background highlight behind text
    });

Merge PDFs

// Merge multiple PDFs into one, preserving page dimensions and resources
byte[] merged = PdfMerger.Merge(new[] { "cover.pdf", "report.pdf", "appendix.pdf" });
File.WriteAllBytes("combined.pdf", merged);

// Or write directly to a file
PdfMerger.MergeToFile(new[] { "file1.pdf", "file2.pdf" }, "merged.pdf");

// Merge with page range selection
byte[] selected = PdfMerger.Merge(new[]
{
    new PdfMergeInput(File.ReadAllBytes("doc1.pdf"), new[] { 1, 3, 5 }),
    new PdfMergeInput(File.ReadAllBytes("doc2.pdf"))  // all pages
});

Split PDFs

// Split into individual pages
List<byte[]> pages = PdfSplitter.Split("input.pdf");

// Extract specific pages (1-based)
byte[] subset = PdfSplitter.ExtractPages("input.pdf", new[] { 1, 3, 5 });

// Split to individual files with naming pattern
PdfSplitter.SplitToFiles("input.pdf", "page_{0}.pdf");

Build PDFs from Scratch

byte[] pdf = PdfBuilder.Create()
    .WithMetadata(m => m.Title("Report").Author("Exis"))
    .AddPage(page => page
        .Size(PdfPageSize.A4)
        .AddText("Hello, World!", x: 72, y: 750, fontSize: 24,
            options: o => o.Font("Helvetica").Bold().Color(0, 0, 0.8))
        .AddText("Generated with Exis.PdfEditor", x: 72, y: 720, fontSize: 12)
        .AddLine(72, 710, 523, 710, strokeWidth: 1)
        .AddRectangle(72, 600, 200, 80, fill: true,
            fillRed: 0.95, fillGreen: 0.95, fillBlue: 1.0)
        .AddImage(jpegBytes, x: 300, y: 400, width: 200, height: 150))
    .AddPage(page => page
        .Size(PdfPageSize.Letter)
        .AddText("Page 2", x: 72, y: 700, fontSize: 14))
    .Build();

File.WriteAllBytes("output.pdf", pdf);

Extract Text

// Extract all text from a PDF
PdfTextResult text = PdfTextExtractor.ExtractText("input.pdf");
Console.WriteLine(text.FullText);

// Extract from specific pages only
PdfTextResult partial = PdfTextExtractor.ExtractText("input.pdf", new[] { 1, 3 });

// Structured extraction with position and font data
PdfStructuredTextResult structured = PdfTextExtractor.ExtractStructured("input.pdf");
foreach (var block in structured.Pages[0].TextBlocks)
    Console.WriteLine($"[{block.X:F0},{block.Y:F0}] {block.Text} " +
        $"(font={block.FontName}, size={block.FontSize})");

Inspect Document (No License Required)

PdfDocumentInfo info = PdfInspector.Inspect("input.pdf");

Console.WriteLine($"Pages: {info.PageCount}");
Console.WriteLine($"Title: {info.Title}");
Console.WriteLine($"Fonts: {string.Join(", ", info.FontsUsed)}");
Console.WriteLine($"Encrypted: {info.IsEncrypted}");
Console.WriteLine($"Form fields: {info.FormFieldCount}");

Image Replacement

// Find all images in a PDF
var found = PdfImageEditor.FindImages("input.pdf");
foreach (var img in found.Images)
    Console.WriteLine($"Image #{img.Index}: {img.PixelWidth}x{img.PixelHeight} " +
        $"{img.ColorSpace} {img.Format} on page(s) {string.Join(", ", img.PageNumbers)}");

// Replace all images with a new one
byte[] newLogo = File.ReadAllBytes("new-logo.jpg");
var result = PdfImageEditor.ReplaceAll("input.pdf", "output.pdf", newLogo);
Console.WriteLine($"Replaced {result.ImagesReplaced} of {result.ImagesFound} images");

// Replace specific images by index or page range
var selective = PdfImageEditor.Replace("input.pdf", "output.pdf", newLogo,
    new PdfImageReplaceOptions { ImageIndices = new[] { 0, 2 } });

Auto-Layout Document Builder

byte[] pdf = PdfDocumentBuilder.Create()
    .PageSize(PdfPageSize.A4)
    .Margins(72)
    .WithMetadata(m => m.Title("Report").Author("Exis"))
    .Header(h => h
        .AddText("Quarterly Report", PdfHorizontalAlignment.Center, 12, o => o.Bold())
        .AddLine())
    .Footer(f => f
        .AddLine()
        .AddPageNumber())  // "Page 1 of 3"
    .AddParagraph("Introduction", 18, o => o.Bold())
    .AddSpacing(8)
    .AddParagraph("This report covers Q1 results.")
    .AddSpacing(12)
    .AddTable(t => t
        .Columns(2, 1, 1)
        .AlternatingRowBackground(0.95, 0.95, 1.0)
        .HeaderRow(r => r.AddCell("Product").AddCell("Units").AddCell("Revenue"))
        .AddRow(r => r.AddCell("Widget A").AddCell("1,200").AddCell("$24,000"))
        .AddRow(r => r.AddCell("Widget B").AddCell("850").AddCell("$17,000")))
    .AddPageBreak()
    .AddParagraph("Appendix", 14, o => o.Bold())
    .Build();

Form Filling

// Read form fields
List<PdfFormField> fields = PdfFormFiller.GetFields("form.pdf");
foreach (var field in fields)
    Console.WriteLine($"{field.Name} ({field.FieldType}) = {field.CurrentValue}");

// Fill fields
var result = PdfFormFiller.Fill("form.pdf", "filled.pdf", new Dictionary<string, string>
{
    { "FirstName", "John" },
    { "LastName", "Doe" },
    { "State", "CA" },
    { "AgreeToTerms", "Yes" }  // checkbox
});
Console.WriteLine($"Filled {result.FieldsFilled} fields");

// Flatten form (merge field appearances, remove interactive fields)
PdfFormFiller.Flatten("filled.pdf", "flattened.pdf");

Redaction

var result = PdfRedactor.Redact("input.pdf", "redacted.pdf", new[]
{
    // Text-based redaction
    new PdfRedaction { Text = "CONFIDENTIAL" },

    // Regex pattern (e.g., SSN)
    new PdfRedaction { Text = @"\d{3}-\d{2}-\d{4}", IsRegex = true },

    // Replace with alternative text
    new PdfRedaction { Text = "SECRET", ReplaceWith = "[REDACTED]" },

    // Area-based redaction on specific page
    new PdfRedaction { PageNumber = 3, Area = new PdfRect(100, 200, 300, 50) }
});
Console.WriteLine($"Applied {result.RedactionsApplied} redactions");

Optimization

var result = PdfOptimizer.Optimize("input.pdf", "optimized.pdf", new PdfOptimizeOptions
{
    CompressStreams = true,
    RemoveDuplicateObjects = true,
    RemoveMetadata = false,
    DownsampleImages = true,
    MaxImageDpi = 150
});
Console.WriteLine($"Saved {result.BytesSaved} bytes ({result.ReductionPercent:F1}%)");
Console.WriteLine($"Images downsampled: {result.ImagesDownsampled}");

Digital Signatures (.NET 8, 9, 10+)

using System.Security.Cryptography.X509Certificates;

// Sign a PDF
var cert = new X509Certificate2("certificate.pfx", "password");
PdfSigner.Sign("input.pdf", "signed.pdf", new PdfSignOptions
{
    Certificate = cert,
    Reason = "Approved",
    Location = "New York",
    ContactInfo = "admin@example.com"
});

// Verify a signed PDF
PdfSignatureInfo info = PdfSigner.Verify("signed.pdf");
Console.WriteLine($"Signed: {info.IsSigned}");
Console.WriteLine($"Valid: {info.IsValid}");
Console.WriteLine($"Signer: {info.SignerName}");
Console.WriteLine($"Certificate: {info.CertificateSubject}");
Console.WriteLine($"Issuer: {info.CertificateIssuer}");
Console.WriteLine($"Timestamp: {info.HasTimestamp}");

// Verify all signatures in a multi-signed document
List<PdfSignatureInfo> all = PdfSigner.VerifyAll("multi-signed.pdf");
foreach (var sig in all)
    Console.WriteLine($"{sig.SignerName}: valid={sig.IsValid}");

PDF/A Compliance

// Validate (no license required)
// Levels: PdfA1b, PdfA2b, PdfA2u, PdfA3b, PdfA3u
PdfAValidationResult result = PdfAConverter.Validate("input.pdf", PdfALevel.PdfA2b);
Console.WriteLine($"Compliant: {result.IsCompliant}");
foreach (var v in result.Violations)
    Console.WriteLine($"  [{v.Code}] {v.Message} (auto-fix: {v.CanAutoFix})");

// Convert to PDF/A
byte[] pdfa = PdfAConverter.Convert("input.pdf", PdfALevel.PdfA2b);
File.WriteAllBytes("output-pdfa.pdf", pdfa);

Async API

// All I/O operations have async overloads with CancellationToken support
byte[] merged = await PdfMerger.MergeAsync(inputPaths, cancellationToken);
PdfTextResult text = await PdfTextExtractor.ExtractTextAsync(stream, cancellationToken);
var info = await PdfInspector.InspectAsync(path, cancellationToken);
var result = await PdfOptimizer.OptimizeAsync(data, options, cancellationToken);
var sigs = await PdfSigner.VerifyAllAsync(path, cancellationToken);

// Pattern: ClassName.MethodNameAsync(...) on all classes

Exis.PdfEditorの比較

機能 Exis.PdfEditor IronPDF Spire.PDF Aspose.PDF Syncfusion
コンテンツストリームの直接編集 HTMLレンダリング 墨消しオーバーレイ フラグメント置換 墨消しオーバーレイ
フォームフィールドを保持 部分的 部分的
デジタル署名を保持 未変更ページ
テキスト間隔/カーニングを保持 部分的
ネイティブ依存なし 純粋な.NET Chromiumエンジン
DLLサイズ < 500 KB ~250 MB ~20 MB ~40 MB ~15 MB
バッチマルチペア置換 シングルパス 手動ループ 手動ループ 手動ループ 手動ループ
.NET Framework 4.8 .NET 6+のみ
クロスプラットフォーム
正規表現サポート
価格(開発者/年) $499 $749 $999 $1,175 $995*
本社 🇺🇸 USA 🇺🇸 USA 🇨🇳 China 🇦🇺 Australia 🇺🇸 USA

2026年2月時点の公開ドキュメントに基づく比較。機能サポートはバージョンにより異なる場合があります。
「コンテンツストリームの直接編集」とは、ライブラリがPDFテキストオペレータを変換、再レンダリング、オーバーレイなしにその場で変更することを意味します。

機能

PDFの直接編集

コンテンツストリームオペレータを変更。中間変換なし。

ゼロ依存

Ghostscript不要、LibreOffice不要、Chromium不要。純粋なマネージド.NET。

ロスレス出力

フォーム、署名、注釈、ブックマーク — すべて保持。

マルチターゲット

.NET 8, 9, 10+、.NET Standard 2.0 (.NET Framework 4.6.1+、.NET Core 2.0+、.NET 5-7)。

バッチ処理

複数の検索/置換ペアを1回のパスで実行。

正規表現

パターンベースの置換に完全な.NET regexサポート。

クロスプラットフォーム

Windows、Linux、macOS。.NETが動くすべての場所で。

小さなフットプリント

単一DLL、500 KB未満。デプロイするネイティブバイナリなし。

PDF Merge

Combine multiple PDFs into one document, preserving page dimensions and resources.

PDF Split

Extract individual pages or page ranges into separate PDFs. Split to files with naming patterns.

PDF Builder

Create PDFs from scratch with a fluent API. Add text, images, lines, and rectangles with full formatting control.

Text Extraction

Pull text content from PDF pages. Extract from all pages or specific page ranges.

Document Inspector

Read metadata, fonts, page dimensions, and form field counts. Works without any license.

Image Replacement

Find, analyze, and replace images in PDFs. Swap logos or graphics by index or page range with JPEG/PNG.

Auto-Layout Builder

Create reports with auto-pagination, text wrapping, tables, headers/footers, and page numbers.

Form Filling

Read and fill AcroForm fields including text, checkbox, and dropdown. Lossless form preservation.

Redaction

Text-based, regex pattern, or area-based redaction. Permanently remove sensitive content from PDFs.

Optimization

Compress streams, remove duplicate objects, and reduce file size while preserving document quality.

Digital Signatures

Sign PDFs with X.509 certificates and verify existing signatures. Available on .NET 8, 9, 10+.

PDF/A Compliance

Validate and convert to PDF/A (1b, 2b, 2u, 3b, 3u) for long-term archival. Validation works without a license.

Async API

All I/O operations have async overloads with CancellationToken support for scalable applications.

価格

Annual Subscription
$499
auto-renews yearly / cancel anytime
  • 無制限ページ
  • 無制限ファイル
  • 全機能含まれる
  • メールサポート
  • Automatic annual renewal

NuGetパッケージをインストールしてExisLicense.Initialize()を呼び出す — 14日間フル機能。トライアル後、評価モードはドキュメントあたり最大3ページを処理。透かしなし。準備ができたらofficefindreplace.com/Home/pdf-find-replace-csharpでライセンスキーを購入。

価格は米ドル。開発者あたり1キー。開発機、ビルドサーバー、本番環境で動作 — マシン単位やデプロイ単位の制限なし。

トライアルの仕組み

トライアル(1〜14日)

  • NuGetパッケージをインストール
  • ExisLicense.Initialize()を呼び出す
  • フルアクセス — 無制限ページ
  • キー不要、サインアップ不要、クレジットカード不要

評価(14日後)

  • トライアルは自動的に期限切れ
  • ライブラリは動作を継続
  • ドキュメントあたり3ページに制限
  • 出力に透かしなし
  • 既存のコードはそのまま動作

ライセンス済み

  • officefindreplace.com/Home/pdf-find-replace-csharpでキーを購入
  • ExisLicense.Initialize("あなたのキー")を呼び出す
  • 無制限ページ、制限なし
  • サイレント動作 — コンソールメッセージなし

トライアルモードとライセンスモードでコードは変わりません。準備ができたらキーを追加するだけです。

Exis LLCが開発

アメリカ製 — Exis LLC、ニュージャージー州。米国拠点の開発とサポート。
政府からの信頼 — 同じPDFエンジンがGlobal Office Find Replace Professionalを動かしており、米国連邦機関の文書処理に使用されています。
ソフトウェア35年以上 — 文書処理、センサー、暗号化、産業オートメーションにわたる8件の特許。
迅速なサポート — 開発チームへの直接メールアクセス。チケットキューではありません。

よくある質問

いいえ。Exis.PdfEditorは外部依存ゼロの純粋な.NETライブラリです。Office、Acrobat、Ghostscript、LibreOffice、Chromium、その他の外部ツールを使用しません。
IronPDFはChromiumエンジンでPDFをレンダリング — ページを再作成し、フォームフィールド、間隔、署名を破壊します。Aspose.PDFはテキストフラグメント置換アプローチを使用し、位置がずれる可能性があります。Exis.PdfEditorはPDFコンテンツストリームオペレータを直接操作し、対象のテキスト以外すべてを保持します。
フォームフィールド(AcroForms)、チェックボックス、ラジオボタン、デジタル署名(未変更ページ)、注釈、ブックマーク、埋め込みファイル、ハイパーリンク、そしてすべてのレイアウトと間隔。対象のテキストのみが変更されます。
はい。開発者シートライセンスは開発機、ビルドサーバー、本番デプロイをカバーします。マシン単位やデプロイ単位のライセンスはありません。
ライブラリは評価モードに入ります。動作を継続しますが、ドキュメントあたり3ページに制限されます。例外なし、透かしなし。既存のコードはそのまま動作します。準備ができたらライセンスキーを追加してください。
はい。NuGetパッケージには.NET Standard 2.0ビルドが含まれ、.NET Framework 4.6.1以降(4.8含む)で動作します。.NET 8最適化ビルドも同梱。
開発者あたり1つのライセンスキー。キーはソースコード内に配置。開発機、ビルドサーバー、ステージング、本番環境でマシン制限なく動作。チームの場合、各開発者に固有のキーが必要。マシンフィンガープリントやアクティベーションサーバーは不要。
はい。PdfTextExtractor.ExtractText()が全テキスト内容を返します。PdfInspector.Inspect()がドキュメントメタデータとページ数を返します — PdfInspectorはライセンス不要です。
Exis.PdfEditorはテキストがコンテンツストリームにエンコードされたテキストベースのPDFで動作します。コンテンツがラスター画像のスキャンドキュメントの場合、まずOCRを実行してテキストレイヤーを生成する必要があります。
ライブラリはフォントエンコーディングを自動解決 — ToUnicode CMap、WinAnsiEncoding、MacRomanEncoding、/Differences付きカスタムエンコーディング辞書、CJKテキスト用の複合(CID/Type0)フォント。

14日間の無料トライアルを開始

dotnet add package Exis.PdfEditor

無料トライアルを開始 Sample App on GitHub

ご質問は?support@exisone.comにメール — ボットではなく開発者がお答えします。