【问题标题】:How can I read a string from PDF file in C?如何从 C 中的 PDF 文件中读取字符串?
【发布时间】:2020-09-01 16:34:29
【问题描述】:

我想创建一个程序来处理两个文件的编辑距离,我的代码适用于从 txt 文件中读取的字符串。但现在我想从 PDF DOC exc 中读取字符串。如何从这些文件中读取字符串?我尝试了 func fread 但它不起作用。 这是我写的代码:

void method () {
FILE *file;
char *str;
if ((file = fopen("C:/Users/latin/Desktop/prova.pdf", "rb")) == NULL) {
    printf("Error!\n");
}
fread(&str,18,1,file);
printf("%s",str);
}

prova.pdf 是一个包含以下字符串的 PDF 文件:ciaoCiao merendina

【问题讨论】:

  • 分析 PDF 文件可能很棘手。如果您使用示例文本创建文字处理器文档并将其转换为 PDF,则生成的 PDF 文件不一定包含未更改的字符串。它可能会被拆分为多个部分,甚至可以转换为图形元素。您可能需要一个可以从 PDF 文件中提取文本的库或一个将 PDF 转换为文本的库/程序。
  • PDF 根本不是文本格式。不过,它是一个开放标准,因此您可以编写一些可以从中读取的内容。如果可能的话,最好获取一个免费的库来为你做这件事。 resources.infosecinstitute.com/pdf-file-format-basic-structure/…
  • 在某处我读到我可以从 PDF 中读取字符串并读取它的二进制代码。你知道怎么做吗?
  • 你读错了。在不理解和使用 PDF 文件结构格式的情况下,没有通用的方法可以简单地从 PDF 文件中读取文本。

标签: c string pdf char doc


【解决方案1】:

可以用纯 C 语言做到这一点。Adobe 做到了。 Artifex 做到了。其他人已经做到了。但正如评论所言,这是一项繁重的工作。但我可以概述一下步骤,让您了解所涉及的内容。

首先,您可以在开头阅读“幻数”并检查它是否真的是 PDF。它应该以%PDF- 开头,后跟一个版本号。但显然很多 PDF 制作者并不符合这个要求。

接下来,您需要跳到文件的最后并向后阅读,寻找类似的内容:

startxref
1581
%%EOF

该数字是 X-Reference 表开头的字节偏移量,该表列出了文件中所有“对象”的二进制偏移量。对象可以是页面、字体、内容流或许多其他东西。

查看 X-Reference 表,您会看到如下内容:

xref
0 4
0000000000 65535 f 
0000000010 00000 n 
0000000063 00000 n 
0000000127 00000 n 
0000000234 00000 n 
trailer
<<
  /Root 1 0 R
  /Size 4
>>

/Root 1 0 R 行告诉您哪个对象是文档树的根。您需要检查此对象以找到如下所示的顶级 Pages 对象:

2 0 obj
<< /Kids [ 3 0 R ] 
/Type /Pages 
/Count 1 
>> 
endobj

这里的 Kids 元素包含对第一个 Page 对象的引用,如下所示:

3 0 obj
<< /Contents [ 4 0 R ] 
/MediaBox [ 0.0 0.0 612.0 792.0 ] 
/Type /Page 
/Parent 2 0 R 
>> 
endobj

然后您需要找到此处引用的 Contents 对象。内容流(如果未加密或压缩)将向您显示绘制到页面的绘图命令和文本命令。

5 0 obj
<<
  /Length 15660 
>>
stream
BT F1 10.0 Tf 30.0 750.0 Td (<< ) Tj ET BT F1 10.0 Tf 50.0 738.0 Td (/) 
Tj ET BT F1 10.0 Tf 56.0586 738.0 Td (astring) Tj ET BT F1 10.0 Tf 86.7852 
738.0 Td ( ) Tj ET BT F1 10.0 Tf 89.2852 738.0 Td (\() Tj ET BT F1 10.0 Tf 
92.6133 738.0 Td (this string data) Tj ET 
[...lots more commands follow...]
endstream
endobj

文本命令将始终被 BT ... ET 括起来。在这里,您终于可以看到包裹在括号中的字符串。但是您必须注意每个字符串的坐标30.0 750.0 Td 以确定哪些是同一逻辑行的一部分。

如果 PDF 是从文字处理器创建的,它可能包含这种形式的文本,但有很多警告。它可能对字体进行了重新编码,并且文本字符串将不再代表 ASCII 字符,而只是字体编码向量中的位置。如果 PDF 是从扫描的文档创建的,它可能只包含页面的图像,根本没有文本内容,除非它经过了涉及 OCR 的转换。

【讨论】:

  • "它必须以 %PDF- 开头,后跟版本号。" - 虽然理论上是正确的,但这是一个糟糕的建议,因为许多 PDF 文件不遵循这个简单的规则。
  • 程序应该不检查,还是不坚持(打印警告并继续)?
  • 我的建议是完全忽略它。此类 PDF 文件通常会被 Adob​​e Acrobat 或 Adob​​e Reader 等 PDF 阅读器接受,并且警告用户有关在其他 PDF 阅读器中打开而没有警告的文件只会导致沮丧:)
  • 通过文档转换创建的 pdf 的详细信息 -- 对于掉在扫描仪上并扫描为 pdf 的东西没有多大帮助...可能想就差异说一两句话。
猜你喜欢
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 2010-12-03
  • 1970-01-01
  • 2014-06-06
相关资源
最近更新 更多