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