Fer*_*cio 40
PoDoFo不提供从文档中轻松提取文本的方法,但这并不难.
将文档加载到PdfMemDocument:
PoDoFo::PdfMemDocument pdf("mydoc.pdf");
Run Code Online (Sandbox Code Playgroud)
遍历每个页面:
for (int pn = 0; pn < pdf.GetPageCount(); ++pn) {
PoDoFo::PdfPage* page = pdf.GetPage(pn);
Run Code Online (Sandbox Code Playgroud)
迭代该页面上的所有PDF命令:
PoDoFo::PdfContentsTokenizer tok(page);
const char* token = nullptr;
PoDoFo::PdfVariant var;
PoDoFo::EPdfContentsType type;
while (tok.ReadNext(type, token, var)) {
switch (type) {
case PoDoFo::ePdfContentsType_Keyword:
// process token: it contains the current command
// pop from var stack as necessary
break;
case PoDoFo::ePdfContentsType_Variant:
// process var: push it onto a stack
break;
default:
// should not happen!
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
"进程令牌"和"进程变量"注释是它变得更复杂的地方.您将获得要处理的原始PDF命令.幸运的是,如果你实际上没有渲染页面而你想要的只是文本,你可以忽略它们中的大部分.您需要处理的命令是:
BT,ET,Td,TD,Ts,T,Tm,Tf,",',Tj和TJ
该BT和ET命令标记文本流的开头和结尾,所以你要忽略任何一间不BT/ ET对.
PDF语言基于RPN.命令流由推入堆栈的值和从堆栈中弹出值并处理它们的命令组成.
的",',Tj和TJ命令是唯一的,实际上产生文本.",'并Tj返回一个字符串.使用var.IsString()和var.GetString()处理它.
TJ返回一个字符串数组.您可以使用以下内容提取每个:
if (var.isArray()) {
PoDoFo::PdfArray& a = var.GetArray();
for (size_t i = 0; i < a.GetSize(); ++i)
if (a[i].IsString())
// do something with a[i].GetString()
Run Code Online (Sandbox Code Playgroud)
其他命令用于确定何时引入换行符."并'引入换行符.您最好的选择是从Adobe下载PDF规范并查找文本处理部分.它更详细地解释了每个命令的作用.
我发现编写一个小程序非常有用,该程序接收PDF文件并为每个页面转储命令流.
注意:如果你所做的只是提取没有定位信息的原始文本,你实际上并不需要维护一堆var值.所有文本渲染命令最多只有一个参数.您可以简单地假设最后一个值var包含当前命令的参数.
| 归档时间: |
|
| 查看次数: |
21902 次 |
| 最近记录: |