Guide
How to inspect the PDF object graph in C#
Use pdf.Objects for syntax-level inspection of the catalog, trailer, page tree, and indirect
objects.
Prefer high-level wrappers for ordinary document edits. Low-level access is for integrations that require PDF object details that are not yet wrapped by a feature-specific API.
Read the catalog and trailer
The catalog and latest trailer are the usual starting points for document-level structure.
using ZingPDF;
using var pdf = Pdf.Load(File.OpenRead("input.pdf"));
var catalog = await pdf.Objects.GetDocumentCatalogAsync();
var trailer = await pdf.Objects.GetLatestTrailerDictionaryAsync();
Console.WriteLine($"Root reference: {trailer.Root}");
Console.WriteLine($"Catalog object type: {catalog.GetType().Name}");
Inspect the page tree
pdf.Objects.PageTree exposes page-tree helpers below the public Pdf.GetPageAsync(...)
API.
var pageCount = await pdf.Objects.PageTree.GetPageCountAsync();
Console.WriteLine($"Pages: {pageCount}");
await foreach (var pageObject in pdf.Objects.PageTree.EnumeratePagesAsync())
{
Console.WriteLine($"Page object: {pageObject.Id}");
}
Enumerate indirect objects
The object collection is asynchronous because object streams and referenced objects can be parsed on demand.
await foreach (var indirectObject in pdf.Objects)
{
Console.WriteLine($"{indirectObject.Id}: {indirectObject.Object.GetType().Name}");
}
Editing cautions
- Prefer typed wrappers such as
Form,Page, metadata, redaction, and signing APIs when they cover the task. - Direct object mutations can produce invalid PDFs if required dictionary entries, references, xref state, or stream lengths are wrong.
- After replacing an indirect object, call
pdf.Objects.Update(indirectObject)so the save pipeline writes the changed object. Delete(...)marks the object as free in the next update. It does not scrub previous bytes from older file revisions.
Next step
For high-level save behavior and history removal, see How to rewrite a PDF without incremental history in C#.