Einzelnen Beitrag anzeigen

Ralf Stehle

Registriert seit: 8. Aug 2003
124 Beiträge
 
Delphi 7 Professional
 
#1

Text aus Word.DOC extrahieren (MS-Word 97-2003-Binär-Format:)

  Alt 4. Jan 2014, 12:20
Ich möchte hier einen neuen Thread eröffnen, da ich zu diesem Thema dringend Hilfe benötige.

Ziel:
Aus einer Word-Datei (Word 97-2003) soll ohne installiertes Word und ohne OLE-Automation der reine Ascii-Text extrahiert werden


Zum Aufbau des Word-Binär-Formates gibt es zahlreiche Tutorials im Internet, die ich leider nur teilweise verstehe:

Tutorials:
http://msdn.microsoft.com/de-de/libr...OC_ExtractText
http://msdn.microsoft.com/en-us/libr...OC_ExtractText
http://b2xtranslator.sourceforge.net...y_doc_file.pdf
http://www.opennet.ru/docs/formats/wword8.html#57
http://www.delphigroups.info/2/bf/478477.html
http://www.devmedia.com.br/forum/com...stalado/360243

Komponenten:
Bei http://www.scalabium.com gibt es auch eine schöne Komponente TMSWordDocument.
Ich möchte den Aufbau der Worddateien jedoch gerne selbst verstehen.



Erster Versuch den Aufbau der Word-Datei zu verstehen:
Word-Datei im Hex-Editor öffnen und Versuch, den Aufbau zu vestehen scheitert. Ich kann den File-Information-Block (FIB) nicht sicher identifizieren. Laut Tutorials müsste am Longbyte 0x0018 ein Eintrag für FcMin stehen. Mit diesem Wert soll die Adresse des Textes gefunden werden:
Zitat:
file offset of first character of text. In non-complex files a CP can be transformed into an FC by the following transformation:
fc = cp + fib.fcMin.
.
Ich finde aber keinen sinnvollen FcMin-Wert. Auch weiß ich nicht wofür derWert CP steht. Im Hex-Editor stehen am Dateianfang vor allem FF-Einträge, so dass ich mir nicht sicher bin, daß der FIB tatsächlich am Byte 0 beginnt:

Test.doc im Hex-Editor:

Dateianfang:
 
D0 CF 11 E0 A1 B1 1A E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 03 00 FE FF 09 00 06 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 26 00 00 00 00 00 00 00 00 10 00 00 28 00 00 00 01 00 00 00 FE FF FF FF 00 00 00 00 25 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF .. ..

Byte-Offset 2544: Hier steht mein Text "DAS IST EIN TEST"
 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 44 41 53 20 49 53 54 20 45 49 4E 20 54 45 53 54 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .. ..




Zweiter Versuch mit Hilfe des Beitrages http://www.delphigroups.info/2/bf/478477.html eine Funktion zu schreiben, die das Auslesen des FIB für mich erledigt. Dieser Versuch scheitert bereits an Fehlermeldung im Compiler wohl durch meine eingeschränkten Delphi-Kenntnissen über Streams, OleStreams und IStreams:

Der Compiler gibt eine Fehlermeldung in der Zeile iStrm.Read(vFIB, SizeOf(vFib)) aus: Inkompatible Typen _FIB und Pointer


Hier mein Delphi-Code:

Delphi-Quellcode:
uses
  Windows, Messages, .....
  OleServer, ComCtrls, ComObj, ActiveX, AxCtrls;

type
  U32 = LongWord;
  S32 = Integer;
  U16 = Word;
  S16 = SmallInt;
  U8 = Byte;
  S8 = ShortInt;

type _FIB = record
  wIdent: U16;   { 0x0000 } 
  nFib: U16;   { 0x0002 } 
  nProduct: U16;   { 0x0004 }
  lid: U16;   { 0x0006 }
  pnNext: S16;   { 0x0008 }
  fDot: U32;   { Bitfield 0x0001 0x000A }
  ...
  fcMin: U32;   { 0x0018 } .
  fcMac: U32;   { 0x001C }
  csw: U16;   { 0x0020 }
  ...
  clw: U16;   { 0x003E }
  ...
end;
  TFIB = _FIB;

....
....

procedure ExtractWordFib();
var
  iStor: IStorage;
  iStrm: IStream;
  vFib : TFib; //Selbst definierter Typ
begin
  //1. Get IStorage via StgOpenStorage(...).
  StgOpenStorage('C:\test.DOC',
            nil, STGM_READ or STGM_SHARE_EXCLUSIVE, nil, 0, iStor);

  //2. Get IStream via IStorage.OpenStream('WordDocument'...).
  iStor.OpenStream('test.Doc',
            nil, STGM_READ or STGM_SHARE_EXCLUSIVE, 0, iStrm);

  //3. Read the FIB via IStream.Read(vFIB, SizeOf(vFIB)) where vFIB is a type of TFIB.
  iStrm.Read(vFIB, SizeOf(vFib));

Hier noch die vollständige Typ-Deklaration für den gesamtem FIB (File Information Block):
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, OleServer, ComCtrls, ComObj, ActiveX, AxCtrls;

type
  U32 = LongWord;
  S32 = Integer;
  U16 = Word;
  S16 = SmallInt;
  U8 = Byte;
  S8 = ShortInt;

type _FIB = record
  wIdent:     U16;   { 0x0000 }  { Magic number. }
  nFib:     U16;   { 0x0002 }    { FIB version written. This will be >= 101 for all Word 6.0 for Windows and after documents. }
  nProduct:     U16;   { 0x0004 }{ Product version written by. }
  lid:     U16;   { 0x0006 }    { Language stamp - localized version. }
  pnNext:     S16;   { 0x0008 }
  fDot:     U32;   { Bitfield 0x0001 0x000A }
  fGlsy:     U32;   { Bitfield 0x0002 }
  fComplex:     U32;   { Bitfield 0x0004 }
  fHasPic:     U32;   { Bitfield 0x0008 }
  cQuickSaves:     U32;   { Bitfield 0x00F0 }
  fEncrypted:     U32;   { Bitfield 0x0100 }
  fWhichTblStm:    U32;   { Bitfield 0x0200 }
  fReadOnlyRecommended:    U32;   { Bitfield 0x0400 }
  fWriteReservation:    U32;   { Bitfield 0x0800 }
  fExtChar:     U32;   { Bitfield 0x1000 }
  fLoadOverride:    U32;   { Bitfield 0x2000 }
  fFarEast:     U32;   { Bitfield 0x4000 }
  fCrypto:     U32;   { Bitfield 0x8000 }
  nFibBack:     U32;   { 0x000C }
  lKey:     U32;   { 0x000E }
  envr:     U32;   { 0x0012 }
  fMac:     U32;   { Bitfield 0x01 0x0013 }
  fEmptySpecial:    U32;   { Bitfield 0x02 }
  fLoadOverridePage:    U32;   { Bitfield 0x04 }
  fFutureSavedUndo:    U32;   { Bitfield 0x08 }
  fWord97Saved:    U32;   { Bitfield 0x10 }
  fSpare0:     U32;   { Bitfield 0xFE }
  chse:     U32;   { 0x0014 }
  chstables:     U16;   { 0x0016 }
  fcMin:     U32;   { 0x0018 }             // In non-complexfiles a CP can be transformed into an FC by the following transformation: fc = cp + fib.fcMin.
  fcMac:     U32;   { 0x001C }             // file offset of last character of text in document text stream+ 1
  csw:     U16;   { 0x0020 }
  wMagicCreated:    U16;   { 0x0022 }
  wMagicRevised:    U16;   { 0x0024 }
  wMagicCreatedPrivate:    U16;   { 0x0026 }
  wMagicRevisedPrivate:    U16;   { 0x0028 }
  pnFbpChpFirst_W6:    S16;   { 0x002A }
  pnChpFirst_W6:    S16;   { 0x002C }
  cpnBteChp_W6:    S16;   { 0x002E }
  pnFbpPapFirst_W6:    S16;   { 0x0030 }
  pnPapFirst_W6:    S16;   { 0x0032 }
  cpnBtePap_W6:    S16;   { 0x0034 }
  pnFbpLvcFirst_W6:    S16;   { 0x0036 }
  pnLvcFirst_W6:    S16;   { 0x0038 }
  cpnBteLvc_W6:    S16;   { 0x003A }
  lidFE:     S16;   { 0x003C }
  clw:     U16;   { 0x003E }
  cbMac:     S32;   { 0x0040 }
  lProductCreated:    U32;   { 0x0044 }
  lProductRevised:    U32;   { 0x0048 }
  ccpText:     U32;   { 0x004C }
  ccpFtn:    S32;
  ccpHdr:     S32;   { 0x0054 }
  ccpMcr:     S32;   { 0x0058 }
  ccpAtn:     S32;   { 0x005C }
  ccpEdn:     S32;   { 0x0060 }
  ccpTxbx:     S32;   { 0x0064 }
  ccpHdrTxbx:     S32;   { 0x0068 }
  pnFbpChpFirst:    S32;   { 0x006C }
  pnChpFirst:     S32;   { 0x0070 }
  cpnBteChp:     S32;   { 0x0074 }
  pnFbpPapFirst:    S32;   { 0x0078 }
  pnPapFirst:     S32;   { 0x007C }
  cpnBtePap:     S32;   { 0x0080 }
  pnFbpLvcFirst:    S32;   { 0x0084 }
  pnLvcFirst:     S32;   { 0x0088 }
  cpnBteLvc:     S32;   { 0x008C }
  fcIslandFirst:    S32;   { 0x0090 }
  fcIslandLim:     S32;   { 0x0094 }
  cfclcb:     U16;   { 0x0098 }
  fcStshfOrig:     S32;   { 0x009A }
  lcbStshfOrig:    U32;   { 0x009E }
  fcStshf:     S32;   { 0x00A2 }
  lcbStshf:     U32;   { 0x00A6 }
  fcPlcffndRef:    S32;   { 0x00AA }
  lcbPlcffndRef:    U32;   { 0x00AE }
  fcPlcffndTxt:    S32;   { 0x00B2 }
  lcbPlcffndTxt:    U32;   { 0x00B6 }
  fcPlcfandRef:    S32;   { 0x00BA }
  lcbPlcfandRef:    U32;   { 0x00BE }
  fcPlcfandTxt:    S32;   { 0x00C2 }
  lcbPlcfandTxt:    U32;   { 0x00C6 }
  fcPlcfsed:     S32;   { 0x00CA }
  lcbPlcfsed:     U32;   { 0x00CE }
  fcPlcpad:     S32;   { 0x00D2 }
  lcbPlcpad:     U32;   { 0x00D6 }
  fcPlcfphe:     S32;   { 0x00DA }
  lcbPlcfphe:     U32;   { 0x00DE }
  fcSttbfglsy:     S32;   { 0x00E2 }
  lcbSttbfglsy:    U32;   { 0x00E6 }
  fcPlcfglsy:     S32;   { 0x00EA }
  lcbPlcfglsy:     U32;   { 0x00EE }
  fcPlcfhdd:     S32;   { 0x00F2 }
  lcbPlcfhdd:     U32;   { 0x00F6 }
  fcPlcfbteChpx:    S32;   { 0x00FA }
  lcbPlcfbteChpx: U32;   { 0x00FE }
  fcPlcfbtePapx:    S32;   { 0x0102 }
  lcbPlcfbtePapx: U32;   { 0x0106 }
  fcPlcfsea:     S32;   { 0x010A }
  lcbPlcfsea:     U32;   { 0x010E }
  fcSttbfffn:     S32;   { 0x0112 }
  lcbSttbfffn:     U32;   { 0x0116 }
  fcPlcffldMom:    S32;   { 0x011A }
  lcbPlcffldMom:    U32;   { 0x011E }
  fcPlcffldHdr:    S32;   { 0x0122 }
  lcbPlcffldHdr:    U32;   { 0x0126 }
  fcPlcffldFtn:    S32;   { 0x012A }
  lcbPlcffldFtn:    U32;   { 0x012E }
  fcPlcffldAtn:    S32;   { 0x0132 }
  lcbPlcffldAtn:    U32;   { 0x0136 }
  fcPlcffldMcr:    S32;   { 0x013A }
  lcbPlcffldMcr:    U32;   { 0x013E }
  fcSttbfbkmk:     S32;   { 0x0142 }
  lcbSttbfbkmk:    U32;   { 0x0146 }
  fcPlcfbkf:     S32;   { 0x014A }
  lcbPlcfbkf:     U32;   { 0x014E }
  fcPlcfbkl:     S32;   { 0x0152 }
  lcbPlcfbkl:     U32;   { 0x0156 }
  fcCmds:     S32;   { 0x015A }
  lcbCmds:     U32;   { 0x015E }
  fcPlcmcr:     S32;   { 0x0162 }
  lcbPlcmcr:     U32;   { 0x0166 }
  fcSttbfmcr:     S32;   { 0x016A }
  lcbSttbfmcr:     U32;   { 0x016E }
  fcPrDrvr:    S32;   { 0x0172 }
  lcbPrDrvr:     U32;   { 0x0176 }
  fcPrEnvPort:     S32;   { 0x017A }
  lcbPrEnvPort:    U32;   { 0x017E }
  fcPrEnvLand:     S32;   { 0x0182 }
  lcbPrEnvLand:    U32;   { 0x0186 }
  fcWss:     S32;   { 0x018A }
  lcbWss:     U32;   { 0x018E }
  fcDop:     S32;   { 0x0192 }
  lcbDop:     U32;   { 0x0196 }
  fcSttbfAssoc:    S32;   { 0x019A }
  lcbSttbfAssoc:    U32;   { 0x019E }
  fcClx:     S32;   { 0x01A2 }
  lcbClx:     U32;   { 0x01A6 }
  fcPlcfpgdFtn:    S32;   { 0x01AA }
  lcbPlcfpgdFtn:    U32;   { 0x01AE }
  fcAutosaveSource:    S32;   { 0x01B2 }
  lcbAutosaveSource:    U32;   { 0x01B6 }
  fcGrpXstAtnOwners:    S32;   { 0x01BA }
  lcbGrpXstAtnOwners:    U32;   { 0x01BE }
  fcSttbfAtnbkmk:    S32;   { 0x01C2 }
  lcbSttbfAtnbkmk:    U32;   { 0x01C6 }
  fcPlcdoaMom:     S32;   { 0x01CA }
  lcbPlcdoaMom:    U32;   { 0x01CE }
  fcPlcdoaHdr:     S32;   { 0x01D2 }
  lcbPlcdoaHdr:    U32;   { 0x01D6 }
  fcPlcspaMom:     S32;   { 0x01DA }
  lcbPlcspaMom:    U32;   { 0x01DE }
  fcPlcspaHdr:     S32;   { 0x01E2 }
  lcbPlcspaHdr:    U32;   { 0x01E6 }
  fcPlcfAtnbkf:    S32;   { 0x01EA }
  lcbPlcfAtnbkf:    U32;   { 0x01EE }
  fcPlcfAtnbkl:    S32;   { 0x01F2 }
  lcbPlcfAtnbkl:    U32;   { 0x01F6 }
  fcPms:     S32;   { 0x01FA }
  lcbPms:     U32;   { 0x01FE }
  fcFormFldSttbs: S32;   { 0x0202 }
  lcbFormFldSttbs:U32;   { 0x0206 }
  fcPlcfendRef:    S32;   { 0x020A }
  lcbPlcfendRef:    U32;   { 0x020E }
  fcPlcfendTxt:    S32;   { 0x0212 }
  lcbPlcfendTxt:    U32;   { 0x0216 }
  fcPlcffldEdn:    S32;   { 0x021A }
  lcbPlcffldEdn:    U32;   { 0x021E }
  fcPlcfpgdEdn:    S32;   { 0x0222 }
  lcbPlcfpgdEdn:    U32;   { 0x0226 }
  fcDggInfo:     S32;   { 0x022A }
  lcbDggInfo:     U32;   { 0x022E }
  fcSttbfRMark:    S32;   { 0x0232 }
  lcbSttbfRMark:    U32;   { 0x0236 }
  fcSttbCaption:    S32;   { 0x023A }
  lcbSttbCaption: U32;   { 0x023E }
  fcSttbAutoCaption:    S32;   { 0x0242 }
  lcbSttbAutoCaption:    U32;   { 0x0246 }
  fcPlcfwkb:     S32;   { 0x024A }
  lcbPlcfwkb:     U32;   { 0x024E }
  fcPlcfspl:     S32;   { 0x0252 }
  lcbPlcfspl:     U32;   { 0x0256 }
  fcPlcftxbxTxt:    S32;   { 0x025A }
  lcbPlcftxbxTxt: U32;   { 0x025E }
  fcPlcffldTxbx:    S32;   { 0x0262 }
  lcbPlcffldTxbx: U32;   { 0x0266 }
  fcPlcfhdrtxbxTxt:    S32;   { 0x026A }
  lcbPlcfhdrtxbxTxt:    U32;   { 0x026E }
  fcPlcffldHdrTxbx:    S32;   { 0x0272 }
  lcbPlcffldHdrTxbx:    U32;   { 0x0276 }
  fcStwUser:     S32;   { 0x027A }
  lcbStwUser:     U32;   { 0x027E }
  fcSttbttmbd:     S32;   { 0x0282 }
  cbSttbttmbd:     U32;   { 0x0286 }
  fcUnused:     S32;   { 0x028A }
  lcbUnused:     U32;   { 0x028E }
  fcPgdMother:     S32;   { 0x0292 }
  lcbPgdMother:    U32;   { 0x0296 }
  fcBkdMother:     S32;   { 0x029A }
  lcbBkdMother:    U32;   { 0x029E }
  fcPgdFtn:     S32;   { 0x02A2 }
  lcbPgdFtn:     U32;   { 0x02A6 }
  fcBkdFtn:     S32;   { 0x02AA }
  lcbBkdFtn:     U32;   { 0x02AE }
  fcPgdEdn:     S32;   { 0x02B2 }
  lcbPgdEdn:     U32;   { 0x02B6 }
  fcBkdEdn:     S32;   { 0x02BA }
  lcbBkdEdn:     U32;   { 0x02BE }
  fcSttbfIntlFld:   S32;   { 0x02C2 }
  lcbSttbfIntlFld:U32;   { 0x02C6 }
  fcRouteSlip:     S32;   { 0x02CA }
  lcbRouteSlip:    U32;   { 0x02CE }
  fcSttbSavedBy:    S32;   { 0x02D2 }
  lcbSttbSavedBy: U32;   { 0x02D6 }
  fcSttbFnm:     S32;   { 0x02DA }
  lcbSttbFnm:     U32;   { 0x02DE }
  fcPlcfLst:     S32;   { 0x02E2 }
  lcbPlcfLst:     U32;   { 0x02E6 }
  fcPlfLfo:     S32;   { 0x02EA }
  lcbPlfLfo:     U32;   { 0x02EE }
  fcPlcftxbxBkd:    S32;   { 0x02F2 }
  lcbPlcftxbxBkd: U32;   { 0x02F6 }
  fcPlcftxbxHdrBkd:    S32;   { 0x02FA }
  lcbPlcftxbxHdrBkd:    U32;   { 0x02FE }
  fcDocUndo:     S32;   { 0x0302 }
  lcbDocUndo:     U32;   { 0x0306 }
  fcRgbuse:     S32;   { 0x030A }
  lcbRgbuse:     U32;   { 0x030E }
  fcUsp:     S32;   { 0x0312 }
  lcbUsp:     U32;   { 0x0316 }
  fcUskf:     S32;   { 0x031A }
  lcbUskf:     U32;   { 0x031E }
  fcPlcupcRgbuse: S32;   { 0x0322 }
  lcbPlcupcRgbuse:U32;   { 0x0326 }
  fcPlcupcUsp:    S32;
  lcbPlcupcUsp:    U32;   { 0x032E }
  fcSttbGlsyStyle:S32;
  lcbSttbGlsyStyle: U32;   { 0x0336 }
  fcPlgosl:     S32;   { 0x033A }
  lcbPlgosl:     U32;   { 0x033E }
  fcPlcocx:    S32;
  lcbPlcocx:     U32;   { 0x0346 }
  fcPlcfbteLvc: S32;   { 0x034A }
  lcbPlcfbteLvc: U32;   { 0x034E }
  ftModified: filetime;   { 0x0352 }
  fcPlcflvc:    S32;
  lcbPlcflvc: U32;   { 0x035E }
  fcPlcasumy: S32;   { 0x0362 }
  lcbPlcasumy: U32;   { 0x0366 }
  fcPlcfgram: S32;   { 0x036A }
  lcbPlcfgram: U32;   { 0x036E }
  fcSttbListNames:S32;   { 0x0372 }
  lcbSttbListNames:   U32;   { 0x0376 }
  fcSttbfUssr: S32;   { 0x037A }
  lcbSttbfUssr:    U32;   { 0x037E }
end;
  TFIB = _FIB;

type
  TForm1 = class(TForm)
  ...
Für eure Hilfe bin ich sehr dankbar
Ralf Stehle
ralfstehle@yahoo.de

Geändert von Ralf Stehle ( 4. Jan 2014 um 12:27 Uhr)
  Mit Zitat antworten Zitat