Posted by Stealth on March 17, 1998 at 18:36:13:
In Reply to: Re: MORE GOB file questions :) posted by Dr. GrooveuX on March 17, 1998 at 17:53:21:
> > A gob is just a binary file you can read in as records.
> > 1. the main header record
> > 2. the items records(filenames & offsets etc for the filedata inside)
> > 3. file data records
> > The directories are stored as filepaths in the item records.
> > You need to read the main header (16 bytes) to get the number of files inside the gob
> Ok, so the part the says GOB is ascii text? that occupies the first 3 bytes so i can skip it? then the gob version, that occupies one byte so i can jsut skip over it? and then the other numbers as type Long, i can just read those in as long integers?
>
> > Then read 128 bytes for each file in the gob, This contains the filepath(name) size of file and starting offset from the begining of the file ( for each file inside of the gob)
> so you could use a do(while) statement...
Well it depends on how you wnat to make your program . The easiest thing is to extract all the files one after another. For this you could use a loop
> > Finally you position yourself at the offset and read the size in bytes for the file you want.
> gotcha
> Sorry about all this mass confusion, I'm just trying to get aquainted with reading binary files into my own programs. Just another skill I must master :).
Well we all started someplace :-)
Ok heres some pascal i used if it will help..first define some records (variables)
Type
GobHeaderRec = record
Magic:array[1..3] of char;
version:byte;
version1:longint;
version2:longint; // a pascal longint is 4 bytes long
NumGobItems:longint;
end; //GobHeaderGobItemRec = record
fileoffset:longint;
LenOfFile:Longint;
NameOfFile:array[1..128] of char;
end; //GobItemThen i made an array of gob item records (this holds the files information) 4k of files in a gob would be plenty.
GOB1:GobHeaderRec;
GOB2:array [0..4095]of GobItemRec;
Now first thing is to read the main header,This procedure does that it is passed the name of the file.
Then it reads 1 record of the size specified for the gob header above (16 bytes).I`m only intersted in the version (make sure it`s not a DF Gob) and the number of items(files) in the gobfile.Procedure GetGobHeader(SourceF: String);
var
Count:integer;
Begin
NOTJKGOB:=False;
AssignFile(InPut,SourceF);
Reset(Input);
if not Eof(Input) then BlockRead(InPut,GOB1,1,Count);
if GOB1.version <>32 then
begin
MessageDlg('File is Not A Jedi Knight GOB ?' ,mterror,[mbabort],0);
NotJKGOB:=TRUE;
end;
CloseFile(INPUT);
End;
You could combine this next operation withthe above one, but i needed to do other things.Next you need to get the file starting offsets,the file names,and the file sizes
this is done by reading in entirely the whole Items record(the array).I reopened the file seek 16 bytes into it.(already read that) then for the number of files in the gob read blocks of 136 bytes.
this is stored in the array of gobitems recordsProcedure GetGobItems(SourceF: String);
Var
Count:longint;
X:longint;
Begin
IF NOTJKGOB= TRUE THEN exit;
AssignFile(InPut,SourceF);
Reset(Input,1);
Seek(Input,16);
if not Eof(Input) then for x:=0 to gob1.NuMGobItems-1 do BlockRead(InPut,GOB2[x],136,Count);
Closefile(Input);
End;Finally read the actual data and write to the files creating directories as needed.
using the sizes,offsets,and file names from the item records arrayProcedure ExtractGobItems(const DestPath,SourceF: String);
var
size,X:longint;
Itempath,Itempath1:string;
Begin
IF NOTJKGOB=TRUE Then exit;
AssignFile(InPut,SourceF);
Reset(Input,1);
for x:=0 to gob1.NuMGobItems-1 do
begin
Itempath:=TrimRight(Gob2[x].NameOfFile);
Itempath1:=ExtractFilePath(ItemPath);
Seek(Input,Gob2[x].fileoffset);
AssignFile(OutPutF,DestPath+Itempath);
if not DirectoryExists(DestPath+ItemPath1) then CreateDir(DestPath+ItemPath1);
Rewrite(OutputF,1);
size:=Gob2[x].LenOfFile;
CopyData(Input,OutputF,size);
CloseFile(outputF);
end;
CloseFile(input);
End;And this little procedure i borrowed from Alex ,it copies the data from the gob and writes it to the new file in the size specified.
Procedure CopyData(var ffrom,fto:file;size:longint);
var
buf:array[0..32767] of byte;
begin
While size>sizeof(buf) do
begin
BlockRead(ffrom,buf,sizeof(buf));
BlockWrite(fto,buf,sizeof(buf));
Dec(size,sizeof(buf));
end;
BlockRead(ffrom,buf,size);
BlockWrite(fto,buf,size);
end;