工具类和帮助类
实用工具类和辅助类
本指南展示了如何使用 Aspose.PDF 为 .NET 提供的、面向小型、专注的帮助类,这些类用于常见的底层任务:安全原语使用的整数数学、正则表达式搜索配置、PostScript 函数求值、外部字体发现、向量子路径提取、物理文本测量、缓冲内容流编辑、大型内存流以及库版本报告。这些类本身不是入口点,但它们支撑着整个 API 中更高级的文档、文本和渲染操作。
整数数学助手
MathExtensions 是一个小型静态帮助类,库的安全原语内部使用,但在任何需要始终返回非负结果的模运算时都可供通用使用。
// Unlike the C# % operator, Mod never returns a negative value.
int wrapped = MathExtensions.Mod(-3, 5); // 2正则表达式搜索配置
RegexManager 是一个静态类,用于配置文本搜索操作(例如 TextFragmentAbsorber)所使用的正则表达式引擎。设置 MatchTimeout 以限制模式允许运行的时长,并启用 NonBacktracking 以在对性能敏感的搜索中使用非回溯正则引擎。
using var doc = Document.Open(pdfBytes);
// Guard against runaway regex patterns.
RegexManager.MatchTimeout = TimeSpan.FromSeconds(5);
RegexManager.NonBacktracking = true;
var absorber = new TextFragmentAbsorber(@"\d{3}-\d{4}", true);
doc.Pages[1].Accept(absorber);评估 PostScript 函数
PostScriptEvaluator 是一个静态类,用于评估 Type 4 PDF 函数(PDF32000 §7.10.5)——嵌入 PDF 中的 PostScript 计算器程序,例如某些颜色空间和着色定义中使用的程序。
double[] inputs = { 0.5 };
// Evaluate a PostScript calculator program against the input array.
var outputs = PostScriptEvaluator.Evaluate("{ 2 mul }", inputs);外部字体搜索路径
ExternalFontCache 管理在渲染和转换过程中搜索外部(未嵌入)TrueType/OpenType 字体时的文件夹。使用 Instance 获取单例,使用 GetDefaultFontsFolders 检查内置搜索位置,使用 SetFontsFolders 添加或替换它们。
var cache = ExternalFontCache.Instance;
var defaultFolders = cache.GetDefaultFontsFolders();
// reset: false appends to the existing search paths instead of replacing them.
cache.SetFontsFolders(new[] { @"C:\Fonts\Custom" }, reset: false);提取向量子路径
GraphicsAbsorber 遍历页面并将其绘制的向量子路径提取为 SubPath 元素,每个元素都携带其自身的页面空间边界 Rectangle。这对于在不手动解析内容流的情况下检查或测量向量艺术作品非常有用。
using var doc = Document.Open(pdfBytes);
var absorber = new GraphicsAbsorber();
absorber.Visit(doc.Pages[1]);
Console.WriteLine($"Elements found: {absorber.Elements.Count}");
foreach (var element in absorber.Elements)
{
if (element is SubPath subPath)
{
Rectangle bounds = subPath.Rectangle;
Console.WriteLine($"Sub-path bounds: [{bounds.LLX}, {bounds.LLY}, {bounds.URX}, {bounds.URY}]");
}
}物理文本段测量
PhysicalTextSegment 是已吸收的 TextSegment 在页面空间的投影。通过 TextSegment.PhysicalSegment 访问它,以测量字符序列或读取其解析后的 TextState。
using var doc = Document.Open(pdfBytes);
var absorber = new TextFragmentAbsorber();
doc.Pages[1].Accept(absorber);
foreach (TextFragment fragment in absorber.TextFragments)
{
foreach (TextSegment segment in fragment.Segments)
{
PhysicalTextSegment physical = segment.PhysicalSegment;
var width = physical.MeasureSegment(segment.StartCharIndex, segment.EndCharIndex, true);
TextState state = physical.TextState;
}
}缓冲内容流编辑
ContentsAppender,通过 Page.ContentsAppender 访问,缓冲操作以在页面内容流的前面或后面添加内容,并使用 UpdateData 一次性提交。
using var doc = Document.Open(pdfBytes);
Page page = doc.Pages[1];
page.ContentsAppender.AppendToBegin(new GSave());
page.ContentsAppender.AppendToEnd(new GRestore());
page.ContentsAppender.UpdateData();大型内存流
OptimizedMemoryStream 是一种可增长的内存流,通过将数据存储在固定大小的块中,能够超越 MemoryStream 的 2 GB 单数组限制。它继承自 Stream,因此支持常用的读取、写入和定位操作。
using var stream = new OptimizedMemoryStream();
byte[] buffer = System.Text.Encoding.UTF8.GetBytes("large payload");
stream.Write(buffer, 0, buffer.Length);
bool canSeek = stream.CanSeek;
byte[] allBytes = stream.ToArray();库版本信息
BuildVersionInfo 是一个静态类,在运行时公开库的产品名称和版本号——对于诊断和支持请求非常有用。
Console.WriteLine(BuildVersionInfo.Product);
Console.WriteLine(BuildVersionInfo.AssemblyVersion);
Console.WriteLine(BuildVersionInfo.FileVersion);提示与最佳实践
- 在对不受信任或用户提供的模式进行搜索之前,设置
RegexManager.MatchTimeout以避免灾难性的回溯。 - 当您想要完全替换默认搜索路径而不是追加时,请使用
reset: true调用ExternalFontCache.SetFontsFolders。 - 在缓冲可能超过 2 GB 的超大文档或图像数据时,优先使用
OptimizedMemoryStream而不是MemoryStream。 - 始终以
UpdateData()完成一批ContentsAppender编辑——缓冲的操作符在此之前不会提交到内容流中。 GraphicsAbsorber.Elements可能包含除SubPath之外的GraphicElement实例;在强制转换前请检查类型。
常见问题
| 问题 | 原因 | 修复 |
|---|---|---|
| 正则搜索在复杂模式下挂起 | 未在 RegexManager 上配置超时 | 在运行 TextFragmentAbsorber 搜索之前设置 RegexManager.MatchTimeout |
来自 ContentsAppender 的内容流编辑未出现在已保存的文件中 | 从未调用 UpdateData() | 在最后一次 AppendToBegin/AppendToEnd 调用后调用 UpdateData() |
| 自定义字体在渲染时未被识别 | 字体文件夹未注册,或 reset: true 清除了预期的默认设置 | 使用正确的文件夹列表和 reset 值调用 ExternalFontCache.SetFontsFolders |
OutOfMemoryException 在缓冲非常大的输出时 | MemoryStream 达到了 2 GB 的单数组限制 | 使用 OptimizedMemoryStream,它将数据存储为固定大小的块 |
FAQ
为什么 MathExtensions.Mod 与 C# % 运算符不同?
MathExtensions.Mod 总是返回非负余数,而内置的 % 运算符在被除数为负时可能返回负值。
如何阻止基于正则表达式的文本搜索运行时间过长?
在构建或运行使用正则表达式模式的 TextFragmentAbsorber 之前,将 RegexManager.MatchTimeout 设置为 TimeSpan。
SetFontsFolders 是替换现有搜索路径还是添加到其中?
这取决于 reset 参数:传入 true 以替换当前文件夹列表,或传入 false 将新文件夹追加到列表中。
GraphicsAbsorber 实际提取什么?
它通过 GraphicsAbsorber.Visit 将页面的已绘制矢量子路径提取为 SubPath 元素,每个元素都有页面空间的边界 Rectangle。
何时应该使用 OptimizedMemoryStream 而不是 MemoryStream?
当缓冲数据可能接近或超过 2 GB 时,因为 MemoryStream 由单个数组支持,且该数组有此硬性限制。
API Reference 摘要
| 类 / 方法 | 描述 |
|---|---|
MathExtensions.Mod | 用于安全原语的非负整数模辅助工具 |
RegexManager.MatchTimeout | 对基于正则表达式的文本搜索应用的超时 |
RegexManager.NonBacktracking | 启用非回溯正则表达式引擎 |
PostScriptEvaluator.Evaluate | 评估 Type 4 PDF PostScript 计算器函数 |
ExternalFontCache.Instance | 对外部字体缓存的单例访问 |
ExternalFontCache.GetDefaultFontsFolders | 返回默认的外部字体搜索文件夹 |
ExternalFontCache.SetFontsFolders | 添加或替换外部字体搜索文件夹 |
GraphicsAbsorber.Visit | 从页面中提取矢量图形元素 |
GraphicsAbsorber.Elements | 提取的 GraphicElement/SubPath 项集合 |
SubPath.Rectangle | 提取的子路径的页面空间边界矩形 |
PhysicalTextSegment.MeasureSegment | 测量物理文本段的字符范围 |
PhysicalTextSegment.TextState | 已解析的物理文本段的格式化状态 |
ContentsAppender.AppendToBegin | 将操作符缓冲以预置到页面的内容流 |
ContentsAppender.AppendToEnd | 将操作符缓冲以追加到页面的内容流 |
ContentsAppender.UpdateData | 将缓冲的操作符提交到内容流 |
OptimizedMemoryStream | 可在内存中增长的流,超过 2 GB MemoryStream 限制 |
BuildVersionInfo.Product | 运行库的产品名称 |
BuildVersionInfo.AssemblyVersion | 运行库的程序集版本 |
BuildVersionInfo.FileVersion | 运行库的文件版本 |