すべおの費甚でテキストWCBFFおよびDOC

思ったより少し遅れたしたが、さたざたなデヌタ圢匏からテキストを取埗するこずに぀いお䌚話を続けおいたす。 あなたず私は、元々XMLベヌスのファむルdocxずodtを操䜜し、pdfからテキストを読み取り、rtfの内容をプレヌンテキストに倉換する方法に粟通しおいたす。 それでは、おいしく甘いDOC圢匏に移りたしょう。



気配りのある読者がタむトルの奇劙な略語に぀いお尋ねる前に、私はただいく぀かのdocファむルの内容を芋るように頌みたす







コンピュヌタヌリテラシヌのd明期に私たちの倚くがメモ垳でdocファむルを開こうずするず、同様の亀裂が芋られたず思いたす。 しかし、このバむトの混乱から䜕を埗るこずができるのか、自分自身に尋ねたしょう。これは同じ「垆」に他なりたせん。 ここで最も興味深いのは、ファむルからファむルぞの最初の8バむトです。぀たり、hex'ahの"D0 CF 11 E0 A1 B1 1A E1"



、たたはメモ垳の"Ў±"



です。



タむトルの2番目の略語を解読する䟡倀がありたす。 WCBFFはWindows Compound Binary File Formatに他なりたせん。ロシア語では「 Windows Compound binary format files 」のように聞こえたす。 翻蚳を䌁業の良心に任せお、この圢匏がひどい名前でどのように圹立぀か考えおみたしょう。



そのため、CFBは祖先、たたはより正確には、97番目のバヌゞョンから2007幎たでのすべおのMicrosoft Office圢匏のスケルトンです互換性圢匏で保存する堎合。 このCFBは、Wordのテキストを保存するためだけでなく、ExcelシヌトたたはPowerPointプレれンテヌションを保存するためにも䜿甚されたす。 その結果、CFBで「暗号化」されおいるバックボヌンを読み取り、DOC圢匏を考慮しお読み取りデヌタのテキストを芋぀ける必芁がありたす。



CFBたたは小さなファむルシステム



私が蚀ったように、最初のステップはCFBを読むこずです。 CFBは、セクタヌ、ルヌトディレクトリ、およびある皮のファむルを含む、ミニチュアのファむル構造を瀺したす。 このファむルの問題でさえ、通垞のファむルシステムの堎合ず同じです-たずえば、断片化されたセクタヌ。 幞いなこずに、MicrosoftはCFBず他のすべおの「䞊郚構造」圢匏の䞡方のドキュメントを数幎にわたっお公開しおいたす。



情報がCFBファむルにどのようにパックされるかを理解しおみたしょう。 ファむル党䜓はセクタヌに分割されたす-各512バむト新しい、4番目のバヌゞョンでは、セクタヌサむズは4096バむトになりたす。 最初のセクタヌはファむルヘッダヌです。これは䞊蚘のスクリヌンショットで芋たものです。 これヘッダヌには、ファむルから読み取る方法、内容、および順序に関するすべおの情報が含たれおいたす。



ファむル内のデヌタは、同じ512バむトのセグメントFATに栌玍されたす。 セクタヌセグメントに十分なスペヌスがない堎合、残りのデヌタはチェヌン内の次のデヌタに転送されたす。 チェヌンセクタヌは、ファむル党䜓に散圚しおいる可胜性がありたす぀たり、䞊蚘のようにファむルを断片化できたす。 セクタヌチェヌンの敎合性を維持するために、すべおのデヌタが読み取られおいない堎合に珟圚のセクタヌから切り替えるセクタヌを含む特別なセクタヌがありたす。 チェヌンの終わりは、特別な単語ENDOFCHAIN = 0xFFFFFFFE



によっお特城付けられたす。



䞀郚のデヌタでは512バむトが非垞に倧きくなる可胜性があるため、ミニFATず呌ばれる「ミニチュア」セクタヌがありたす。 ミニFATセクタヌの長さは64バむトであるため、このような小さなセグメントは8個たたは64個が1぀のFATセクタヌに収たりたす。 FATたたはミニFATの遞択は、珟圚のデヌタの党長に基づいおいたす。 4096バむトファむルヘッダヌのパラメヌタヌの1぀未満の堎合、mini FATを䜿甚する䟡倀がありたす。それ以倖の堎合はFATです。



CFBファむル内のデヌタは䜕も積み䞊げられおいたせん-ルヌト゚ントリの特別な「ファむル゚ントリ」にルヌトを持぀ツリヌ構造に構造化されおいたす。 各゚ントリの長さは128バむト4たたは32゚ントリが1぀のFATセグメントに収たるで、その名前、タむプストレヌゞ-ストレヌゞ、ストリヌム-ストリヌム、ルヌトストレヌゞ-ルヌトストレヌゞ、空のスペヌス-未䜿甚、子および「兄匟」によっお特城付けられたす芁玠、赀ず黒の朚の色。 さらに、ストリヌムおよびルヌト芁玠の堎合、コンテンツのオフセットや長さなどのパラメヌタヌが発生したす。



したがっお、FSぞの各゚ントリは、「それに添付されたコンテンツ」によっお特城付けられたす。 ストリヌムの堎合、これはルヌト芁玠ミニFATファむルに保存されたデヌタになりたす。



さらに、ファむルにはDIFATず呌ばれる構造があり、FATシヌケンスのチェヌンを持぀セクタヌぞのリンクを保存したす。 最初の109個のDIFATリンクはファむルヘッダヌの最埌にあり、最倧8.5 MBのファむルを「提䟛」できたす。これが十分でない堎合、ヘッダヌには远加のDIFATセクタヌぞのリンクを含めるこずができたす。



この情報は、CFBファむルで発生しおいるすべおの混乱ず揺れを簡単に特城づけたす。 圢匏は、原則ずしおかなりよく文曞化されおいたすリンクはトピックの最埌にい぀もどおりです。マニュアルを思慮深く綿密に読むだけで十分です。 この蚘事の目的は、CFBファむルの操䜜に関する完党な説明ではありたせんでしたので、䞻なこずに移りたしょう-このすべおからドキュメントを読む方法...



Docたたは圌らは私のオフセットを盗んだ



そもそも、3回目の詊行でのみcfbずずもにドキュメント解析を蚘述したず蚀えたす。 その前に、䜕かがどういうわけかあたりよく読めたせんでした。 そしお、ドキュメントに埓っおすべおを行わなければならなかった理由ですが、... CFBでこれが倧きな問題を匕き起こさない堎合手動蚀語ずしおの英語を陀く、DOCの問題が提䟛されたす。



たず、DOCのファむルシステムを読み取り、その䞭のテキストデヌタを探しおいたす。 たあ、仕様を開いたマむクロ゜フトは私たちに莈り物をし、そうする機䌚を䞎えおくれたした。 これを行うには、CFBファむルの芁玠のツリヌ構造内の2぀の゚ントリのみを䜿甚したす。「 WordDocument



」ずいうストリヌムず、状況に応じお「 0Table



」たたは「 0Table



」ずいうストリヌムです。



最初のストリヌムにはWord文曞のテキストが含たれおいたすが、取埗できたせん。 すべおがひどくバむナリであり、逆バむト順のUnicode゚ンコヌディングのその他すべおすべおのCFBファむルのように、泚目に倀したす。 この点に関しお、たず、WordDocumentストリヌムの先頭にあり、バヌゞョンからバヌゞョンぞず曞き蟌たれるFIB ファむル情報ブロックからいく぀かのフィヌルドを読み取りたすWord 97では、このタむトルは玄700バむトでしたが、2007幎にはすでに2000以䞊でした 。



たず、オフセット0x000A



のワヌドを読み取りたす。 0x000A



、 0x0200



ビットを芋぀けたす。このビットの単䜍は、 0Table



テヌブルを凊理し、 0Table



を凊理するこずを0Table



たす。 䞡方のテヌブルを持぀ファむルに出くわしたこずは泚目に倀するので、いずれにせよビットを読む必芁がありたす。



次に、CLXを芋぀ける必芁がありたす-最も お尻 以前に遞択したプレヌトの1぀の重芁な郚分。 このCompLeX



構造䜓は、WordDocumentストリヌムにテキストデヌタのシヌケンスのオフセットず長さを栌玍したす。 CLXの長さずオフセットは、ドキュメントフロヌFIBの0x01A2



および0x01A6 DWORDにありたす。 この情報を受け取った埌、テヌブルストリヌムからCLXを読み取り、プラグを芋぀けたした...



実際、CLXには、可倉サむズの2぀の完党に異なるデヌタ構造䞍芁なRgPrcず重芁なPlcPcdが含たれおいたす。 実際、PgPrcの長さはれロたたは任意のいずれかです。 幞いなこずに、ドキュメントには最初のデヌタを2番目のデヌタから切り離す方法が蚘茉されおいないため、最終的なコヌドでは䜕らかの奇劙な方法で束葉杖を曞く必芁がありたした。



PlcPcdたたは名前でより適切なピヌステヌブルを受け取った埌、この配列を2぀に分割できたす配列lcb i = cp i+1 - cp i



テキストピヌスの長さ lcb i = cp i+1 - cp i



およびpcdピヌス蚘述子。 埌者のそれぞれには、WordDocumentストリヌムのオフセットずfCompress



特性に関する情報この郚分がUnicodeで圧瞮されおいるか、ANSIWindows-1252であるかが含たれおいたす。



結果ずしお生じるピヌスでは、オブゞェクトや画像の挿入など、いく぀かの制埡文字が発生する堎合がありたす。 私のコヌドでは、それらの䞀郚が削陀されたす。残りの特殊文字の解析は読者に任せたす。



コヌドオプション



さお、い぀ものように、コヌドの䞀郚ず゜ヌスぞのリンク

  1. クラスドキュメントは cfbを拡匵したす {
  2. パブリック 関数解析  {
  3. 芪:: 解析   ;
  4. $ wdStreamID = $ this- > getStreamIdByName  "WordDocument"  ;
  5. if  $ wdStreamID === false  { falseを返す ; }
  6. $ wdStream = $ this- > getStreamById  $ wdStreamID  ;
  7. $バむト = $ this- > getShort  0x000A 、 $ wdStream  ;
  8. $ fComplex =  $バむト  0x0004  == 0x0004 ;
  9. $ fWhichTblStm =  $バむト  0x0200  == 0x0200 ;
  10. $ fcClx = $ this- > getLong  0x01A2 、 $ wdStream  ;
  11. $ lcbClx = $ this- > getLong  0x01A6 、 $ wdStream  ;
  12. $ ccpText = $ this- > getLong  0x004C 、 $ wdStream  ;
  13. $ ccpFtn = $ this- > getLong  0x0050 、 $ wdStream  ;
  14. $ ccpHdd = $ this- > getLong  0x0054 、 $ wdStream  ;
  15. $ ccpMcr = $ this- > getLong  0x0058 、 $ wdStream  ;
  16. $ ccpAtn = $ this- > getLong  0x005C 、 $ wdStream  ;
  17. $ ccpEdn = $ this- > getLong  0x0060 、 $ wdStream  ;
  18. $ ccpTxbx = $ this- > getLong  0x0064 、 $ wdStream  ;
  19. $ ccpHdrTxbx = $ this- > getLong  0x0068 、 $ wdStream  ;
  20. $ lastCP = $ ccpFtn + $ ccpHdd + $ ccpMcr + $ ccpAtn + $ ccpEdn + $ ccpTxbx + $ ccpHdrTxbx ;
  21. $ lastCP + =  $ lastCP = 0  + $ ccpText ;
  22. $ tStreamID = $ this- > getStreamIdByName  intval  $ fWhichTblStm  。 "Table"  ;
  23. if  $ tStreamID === false  { falseを返す ; }
  24. $ tStream = $ this- > getStreamById  $ tStreamID  ;
  25. $ clx = substr  $ tStream 、 $ fcClx 、 $ lcbClx  ;
  26. $ lcbPieceTable = 0 ;
  27. $ pieceTable = "" ;
  28. $ pieceCount = 0 ;
  29. $ from = 0 ;
  30. while   $ i = strpos  $ clx 、 chr  0x02  、 $ from   == false  {
  31. $ lcbPieceTable = $ this- > getLong  $ i + 1 、 $ clx  ;
  32. $ pieceTable = substr  $ clx 、 $ i + 5  ;
  33. if  strlen  $ pieceTable  = $ lcbPieceTable  {
  34. $ from = $ i + 1 ;
  35. 続ける ;
  36. }
  37. 䌑憩 ;
  38. }
  39. $ cp = array   ; $ i = 0 ;
  40. while   $ cp [ ] = $ this- > getLong  $ i 、 $ pieceTable   = $ lastCP 
  41. $ i + = 4 ;
  42. $ pcd = str_split  substr  $ pieceTable 、 $ i + 4  、 8  ;
  43. $ text = "" ;
  44. for  $ i = 0 ; $ i < count  $ pcd  ; $ i ++  {
  45. $ fcValue = $ this- > getLong  2 、 $ pcd [ $ i ]  ;
  46. $ isANSI =  $ fcValue  0x40000000  == 0x40000000 ;
  47. $ fc = $ fcValue  0x3FFFFFFF ;
  48. $ lcb = $ cp [ $ i + 1 ] - $ cp [ $ i ] ;
  49. if   $ isANSI 
  50. $ lcb * = 2 ;
  51. 他に
  52. $ fc / = 2 ;
  53. $ part = substr  $ wdStream 、 $ fc 、 $ lcb  ;
  54. if   $ isANSI 
  55. $ part = $ this- > unicode_to_utf8  $ part  ;
  56. $ text = $ part ;
  57. }
  58. $ textを 返し たす 。
  59. }
  60. }
GitHubにコメントを付けおコヌドを取埗できたす 。



文孊



しない方法

トピック「すべおの費甚でのテキスト」に関する他の蚘事ぞのリンク




All Articles