"%PDF-1.7\n1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n7 0 obj\n<<里面大部分内容被我精简过了,中间部分的内容基本是被压缩过的内容,全是乱码,需要特定的算法解压。以上就是通过二进制流读取PDF文件的大概内容,几乎没有可读性可言啊,一般情况下如果不了解PDF格式,基本处于懵逼状态,有强迫症的可能还会崩溃,呵呵开个玩笑哈。上面只是给大家看个全貌啊,PDF文件解析不会这么干啊。以上那坨内容具有实际解析意义的也就是前后1024个字节,在这2048个字节里面,解析工作主要是处理最后面这1024个字节。接下来我们看看具体怎么解析(思路)。 1.首先我们需要索引到交叉引用表(startxref)的地址,后面的数值对应的也就是上一个xref的起始地址,紧跟着后面就是对象总数,这里是12个间接对象。2.接着处理文件尾trailer,获取size对象。3.把流的偏移址移动到交叉引用段xref,获取所有间接对象,过滤掉被释放的对象,f表示该对象被删除。4.获取所有间接对象的属性,从间接对象里面获取对象基地址如0000000009,表示该对象的流地址是9,族个解析。到此所有间接对象初始化已完成,后续就是通过key索引内容,在这里我们的目标很简单就是读取PDF里面的文本内容,包括x、y坐标,字体、大小、颜色等等,还原到这一步,是不是整个PDF文件都是你的菜了,看效果。 上面就是按照之前逻辑思路解析出来PDF文件的所有间接对象,上面这张图片我大概解释一下啊,Catalog根目录对象,position文件流地址索引,pages文档页面树的根结点,引用的是间接对象2 0 R,表示page这个间接对象在2号对象,简单解释就到这吧。到此我们要读取的文本内容、坐标啥的是不是啥都没看到?是的,确实如此,到这里只是把整个PDF文件的所有对象加载出来,而我们需要读取的内容、坐标等信息就包含在它们里面,并且一般情况下被压缩过。 还原文本信息,看到上面这一大坨间接对象,我们怎么找呢?1.我们索引到page这个对象,里面有个资源字典,该字典里面包含了一个间接对象6 0 R,2.接着我们索引到对象号6这个间接对象,在这个对象里面有个属性ToUnicode引用了间接对象7 0 R,3.继续索引到对象号7,是不是很繁琐啊?呵呵,接着来,不要怕繁琐,奇迹会出现的,ADOBE公司出品的必属精品,在这个对象号里面终于发现奇迹快出现了,我们通过偏移址和长度读取这部分二进制流,接着重头戏来了,FlateDecode表示该部分内容通过zlib压缩(可能会有更复杂的操作,带参数),4.通过deflate解压这部分二进制流。还有一种解析方案,直接索引Contents对象号,解析它里面的二进制流,这部分二进制流可以索引所有内容信息,或者间接引用对象,当然这部分二进制流同样需要解压,这里我贴出解析出来的contents和文本内容信息里面的内容吧BT 50.25 770.577 Td /F2 9 Tf // 通过字体资源索引文本内容
/Filter/FlateDecode/Length 219>>\nstream\nx�]��j�0\f��y\n\u001d�Cq���`(\u001d�\u001c���}\0�R�a���\u001c��s�$�\t,\u0010��
\u0013��n�K�.��\u0014ok��:F���b\t\u001a�\u001c\u0017�g@g�2�n{\u0013\n��z\u001a\"�\u0015��,�W��(����\u0010$q���q���
\u001eC���8�Qk�6mx3���2q�0�.N���p�\u0002�S�O�!�G\u001a��$�;*�c*]���\u00051��\u0017�i��g����bfVu��ϭ���\")U�@�3
\aqLۑ�\u000f3��\u000f}�p�\nendstream\nendobj\n10 0 obj\n<</Length1 4960/Filter/FlateDecode/Length ................................ndstream
\nendobj\n9 0 obj\n<</Type/FontDescriptor/FontName/PFWAAB+�o��,Bold/Flags 32/ItalicAngle 0/FontWeight 700/Leading 0/Ascent 1058.105\n
/Descent -261.7188/XHeight 540.0391/AvgWidth 584.9609/CapHeight 756.3477/StemV 160/MaxWidth 1000/FontBBox[12.6953125 -136.23046875
985.3515625 821.77734375]\n/FontFile2 10 0 R>>\nendobj\n11 0 obj\n[3[1000]]\nendobj\n6 0 obj\n<</Type/Font/Subtype/Type0/BaseFont
/PFWAAB+�o��,Bold/Encoding/Identity-H/ToUnicode 7 0 R/DescendantFonts[8 0 R]>>\nendobj\n4 0 obj\n<</Type/Page/Parent 2 0 R
/MediaBox[0 0 595.2756 841.8898]/Contents[5 0 R]/Resources<</ProcSet [/PDF/Text/ImageB/ImageC/ImageI]\n/Font <</F2 6 0 R>>\n>>>>\
nendobj\n5 0 obj\n<</Length 55>>\nstream\nq\nq\n0 0 0 rg\nBT\n50.25 770.577 Td\n/F2 9 Tf(\0\u0003)Tj\nET\nQ\nQ\n\nendstream\nendobj\n8 0 obj
\n<</Type/Font/Subtype/CIDFontType2/BaseFont/PFWAAB+�o��,Bold/CIDSystemInfo<</Ordering(Identity)/Registry(Adobe)\n/Supplement 0>>
\n/FontDescriptor 9 0 R/W 11 0 R>>\nendobj\nxref\n0 12\n0000000000 65535 f \n0000000009 00000 n \n0000000054 00000 n \n0000000000 00000 f
\n0000003905 00000 n \n0000004072 00000 n \n0000003776 00000 n \n0000000105 00000 n \n0000004175 00000 n \n0000003445 00000 n
\n0000000392 00000 n \n0000003750 00000 n \ntrailer\n<</Root 1 0 R/ID[<474b3c8539d96eb244f8fb3f8ed789ac><474b3c8539d96eb244f8fb3f8ed789ac>]
/Size 12>>\nstartxref\n4350\n%%EOF\n"
<0003> Tj /CIDInit /ProcSet findresource begin 14 dict begin begincmap /CIDSystemInfo<</Registry(Adobe)/Ordering (UCS)/Supplement 0>>def /CMapName/Adobe-Identity-UCS def /CMapType 2 def 1 begincodespacerange <0000><FFFF> endcodespacerange 1 beginbfrange <0003> <53cd> // unicode字符集,这就是我们要找的内容 endbfrange endcmap CMapName currentdict /CMap defineresource pop end end拿到以上内容,我们的文本内容属性就全部拿到了,有绘制坐标、字体、size、unicode字符集、编码等内容,到现在是不是简单的一份PDF文件,基本被我们蹂躏了?呵呵,不要急还有比较复杂的一步操作,嵌入的字体文件处理。我们知道字体ttf、ttc其实际就是一堆字符轮廓(有矢量、点、位图),通过设备绘制输出,接下来我们通过对象集合索引出字体文件,看,不要看我,看上面对象集合图,这些不是乱看的啊,通过对象引用追朔下来的啊,在8号对象里面找到属性FontDescriptor 9 0 R表示字体文件描述信息在9号对象里面,继续索引9号对象,最终守得云开见月明,找到属性FontFile2 10 0 R表示trueType字体信息在10号对象,看内容。
............cvt XMTñ.......´fpgm,.·,...P.. .glyfà.3ë.. X...¨head b¬¥.......6hhea.u.....8...$hmtx.[.Í...\....loca.ý.R...l... maxp.O.....x... prep.Kî:.......Å.c.....删了很多信息啊,在里面是不是发现了head hmtx字样,这就是字体文件ttf、ttc字体文件结构,透露一下啊,如果我们自己实现PDF编辑工具,字体嵌入的实现,其实际就是创建这么一个ttf、ttc字体文件。看到上面这些东西,朋友们不要心急啊,这玩意还用不了啊,因为这部分内容信息同样压缩了,需要解压。我们现在还缺少一个步骤,通过字体绘制到显示器,到这里就比较简单了啊,拿到字体文件信息,各平台有加载ttf、ttc的类库,直接加载,然后设置相关字体信息就完成了。题外话,整个嵌入字体文件,如果基于代码实现还是比较复杂的啊,需要非常熟悉trueType、openType等字体结构,差不多就到这吧,写入同样按上面的逻辑来,当然肯里面还有些寻字节偏移址细节,需要自己多注意,写的不对请留言指出谢谢。
标签:文件,对象,字体,00000,内容,PDF,解析 来源: https://www.cnblogs.com/adair-blog/p/14107894.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。