C# / .NET PDF-Bibliothek — PDF Oxide
PDF Oxide ist die schnellste PDF-Bibliothek für .NET: 0,8 ms Textextraktion im Durchschnitt, 5× schneller als PyMuPDF, 15× schneller als pypdf, 100 % Trefferquote auf 3.830 PDFs. Ein Paket für Extraktion, Erstellung und Bearbeitung — NativeAOT-ready, trim-safe, mit idiomatischem using, async Task<T>, CancellationToken und LINQ-freundlichen Collections. Lizenz: MIT / Apache-2.0.
Installation
dotnet add package PdfOxide
Ziel-Frameworks: net8.0 und net10.0. IsAotCompatible=true und IsTrimmable=true sind aktiviert.
Das NuGet-Paket enthält vorgebaute native Bibliotheken für Windows, macOS (Intel + Apple Silicon) sowie Linux (x64 + ARM64). Keine Systemabhängigkeiten, keine Rust-Toolchain erforderlich.
PDF öffnen
using PdfOxide.Core;
using var doc = PdfDocument.Open("research-paper.pdf");
Console.WriteLine($"Seiten: {doc.PageCount}");
Console.WriteLine($"PDF-Version: {doc.Version.Major}.{doc.Version.Minor}");
Aus einem Stream:
using var stream = File.OpenRead("report.pdf");
using var doc = PdfDocument.Open(stream);
Mit Passwort:
using var doc = PdfDocument.OpenWithPassword("secure.pdf", "user-password");
AES-256-PDFs (V=5, R=6) werden vollständig unterstützt.
Page-API
Seit v0.3.34 stellt PdfDocument eine Pages-Eigenschaft (ein IReadOnlyList<PdfPage>) sowie einen int-Indexer bereit, sodass Sie per foreach iterieren und LINQ verwenden können.
using PdfOxide.Core;
using var doc = PdfDocument.Open("paper.pdf");
foreach (var page in doc.Pages)
{
Console.WriteLine($"--- Seite {page.Index + 1} ---");
Console.WriteLine(page.ExtractText());
}
// Oder direkt per Index
PdfPage first = doc[0];
string md = await first.ToMarkdownAsync();
Jede PdfPage bietet eine vollständige synchrone und asynchrone Oberfläche: ExtractText() / ExtractTextAsync(), ToMarkdown(), ToHtml(), ToPlainText(), ExtractWords(), ExtractTextLines(), ExtractTables(), ExtractChars(), ExtractImages(), Search().
Textextraktion
Einzelne Seite
using var doc = PdfDocument.Open("report.pdf");
string text = doc.ExtractText(0);
Console.WriteLine(text);
Alle Seiten
string allText = doc.ExtractAllText();
Seiten manuell durchlaufen
for (int i = 0; i < doc.PageCount; i++)
{
Console.WriteLine($"--- Seite {i + 1} ---");
Console.WriteLine(doc.ExtractText(i));
}
Asynchrone Extraktion
Zu jeder Extraktionsmethode gibt es ein *Async-Pendant, das Task<T> zurückgibt und optional einen CancellationToken entgegennimmt.
using PdfOxide.Core;
using var doc = PdfDocument.Open("large.pdf");
string text = await doc.ExtractTextAsync(0);
// Fan-out mit Abbruch
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);
Vollständige Muster finden Sie im Async-Leitfaden.
Strukturierte Extraktion
var words = doc.ExtractWords(0);
foreach (var (text, x, y, w, h) in words)
{
Console.WriteLine($"\"{text}\" bei ({x:F1}, {y:F1})");
}
// Nach Region
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($"Tabelle {rows}x{cols}");
}
Markdown-Konvertierung
string markdown = doc.ToMarkdown(0);
string allMarkdown = doc.ToMarkdownAll();
HTML-Konvertierung
string html = doc.ToHtml(0);
string allHtml = doc.ToHtmlAll();
Bildextraktion
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} Bytes)");
File.WriteAllBytes($"image_{Array.IndexOf(images.ToArray(), img)}.{img.Format}", img.Data);
}
PDFs mit indizierten Farben werden automatisch nach RGB expandiert (1/2/4/8 bpc mit RGB, Graustufen oder CMYK als Basisfarbraum).
Suche
var results = doc.SearchAll("Quartalsumsatz");
foreach (var (page, text, x, y, w, h) in results)
{
Console.WriteLine($"Seite {page}: \"{text}\" bei ({x}, {y})");
}
// Eine einzelne Seite mit Groß-/Kleinschreibung
var pageResults = doc.SearchPage(0, "exakter Ausdruck", caseSensitive: true);
LINQ lässt sich nahtlos einsetzen:
var hitsByPage = doc.SearchAll("keyword")
.GroupBy(r => r.Page)
.OrderBy(g => g.Key);
foreach (var group in hitsByPage)
{
Console.WriteLine($"Seite {group.Key}: {group.Count()} Treffer");
}
PDF-Erstellung
using PdfOxide.Core;
// Aus Markdown
using (var pdf = Pdf.FromMarkdown("# Rechnung\n\nSumme: **$42,00**"))
{
pdf.Save("invoice.pdf");
}
// Aus HTML
using (var pdf = Pdf.FromHtml("<h1>Bericht</h1><p>Erstellt am 2026-04-09</p>"))
{
pdf.Save("report.pdf");
}
// Aus reinem Text
using (var pdf = Pdf.FromText("Reines Textdokument.\n\nZweiter Absatz."))
{
pdf.Save("notes.pdf");
}
// Aus einem Bild
using (var pdf = Pdf.FromImage("scan.jpg"))
{
pdf.Save("scan.pdf");
}
Bearbeiten — Metadaten und Formulare
using PdfOxide.Core;
using var editor = DocumentEditor.Open("form.pdf");
// Metadaten lesen
Console.WriteLine($"Titel: {editor.Title}");
Console.WriteLine($"Seiten: {editor.PageCount}");
// Metadaten aktualisieren
editor.Title = "Quartalsbericht";
editor.Author = "Finanzabteilung";
editor.Subject = "Ergebnisse Q1 2026";
// Formularfelder füllen und flach zeichnen
editor.SetFormFieldValue("employee.name", "Jane Doe");
editor.SetFormFieldValue("employee.email", "jane@example.com");
editor.FlattenForms();
editor.Save("edited.pdf");
// oder: await editor.SaveAsync("edited.pdf");
Formularfelder nur lesen, ohne zu bearbeiten:
using var doc = PdfDocument.Open("form.pdf");
foreach (var f in doc.GetFormFields())
{
Console.WriteLine($"{f.Name} ({f.FieldType}) = \"{f.Value}\"");
}
Hinweis: Die .NET-Bindung unterstützt derzeit das Öffnen, Lesen, Konvertieren und Erstellen von Dokumenten, Bildextraktion, Lesen, Füllen und Flachzeichnen von Formularfeldern sowie die Bearbeitung von Metadaten. Seitenoperationen, Anmerkungen, Rendering und Signaturen sind im Rust-Kern und in anderen Bindings verfügbar; ein entsprechendes .NET-API folgt in einer zukünftigen Version.
NativeAOT-Publishing
Die .NET-Bindung von PDF Oxide ist für NativeAOT-Publishing vorbereitet:
dotnet publish -c Release -r linux-x64 --self-contained -p:PublishAot=true
Alle 881 P/Invoke-Deklarationen nutzen LibraryImport (source-generated P/Invoke), IsAotCompatible=true und IsTrimmable=true. Ihr AOT-kompiliertes Binary bindet nur die tatsächlich verwendeten Teile ein; der native Rust-Kern wird über die mitgelieferte plattformspezifische Bibliothek statisch gelinkt.
Plugins und Erweiterungen
Das Paket PdfOxide.Plugins (ausgeliefert neben PdfOxide) stellt Erweiterungspunkte für Prozessoren bereit, die extrahierte Inhalte transformieren — Klassifikatoren, Nachbearbeiter, Validatoren. Für die Erstellung von Erweiterungen siehe den Plugin-Leitfaden.
Fehlerbehandlung
Alle Methoden werfen im Fehlerfall typisierte Exceptions:
using PdfOxide.Core;
try
{
using var doc = PdfDocument.Open("document.pdf");
string text = doc.ExtractText(0);
}
catch (PdfOxideException ex)
{
Console.Error.WriteLine($"Fehler in PDF Oxide: {ex.Message}");
}
catch (FileNotFoundException)
{
Console.Error.WriteLine("Datei nicht gefunden");
}
Nächste Schritte
- Python-Einstieg — PDF Oxide in Python nutzen
- C#-API-Referenz — vollständige API-Dokumentation
- Async-Leitfaden — Muster für
Task<T>+CancellationToken - Nebenläufigkeits-Leitfaden — Muster für
ReaderWriterLockSlim - Textextraktion — ausführliche Extraktionsoptionen
- NuGet-Paket — Release Notes und Downloadzahlen