Discussion:
Problem reading a file generated by a Delphi application
(too old to reply)
Ronaldo
2005-04-04 15:32:54 UTC
Permalink
Hi all !! My name is Ronaldo. IŽm from Brazil.
I’m having a hard time on reading a file generated by a Software created through Delphi, it’s not a regular text file, though it is a file that was generated by a component, which main goal is to compress any file using a Zlib, and then to save the bytes from that compressed file as binary fields. That was just a brief introduction so as you can have an idea of the general issue…
My real problem is reading the header and the footer generated by that component (I do not have any problem in reading and decompressing the data compressed with Zlib). At that header, there is information, such as backup title, size of the backup title, total bytes from the original file, total files in backup, the size in bytes of the path + name of the file that was compressed, path + name of the file compressed, date & time of last update on that file, and a signature “EC2” or “ECS”, where the first one indicates that the content is compressed, and the second one indicates that is not…
The component writes some data with more frequency; if I manage to read those, I think I’ll be able of reading the others. I created a Delphi code very simple in order to generate that header, and another one, to read it. I did the same in Java. However, what I generate in Delphi, cannot be read in Java, and vice versa.
I’m going to leave here the source codes in Java and Delphi, in case someone can help me out. Probably somebody already passed through this issue, or at least knows both languages.

I appreciate your help in advance, and apologize for the size of this message.

Obs1 : If somebody try to write a Delphi code, add in implementation clausule :

const
fSignature = 'EC2';

Obs2: In the procedure TForm1.Button2Click(Sender: TObject); lb is TListBox component.

// Delphi code to generate header file
procedure TForm1.Button1Click(Sender: TObject);
var ss : String ;
L: Integer;
FA: integer;
CurrentFile: String;
SStr: TFilestream;
TStr: TStream;
fBackupTitle : String ;
fSizeTotal, fFilesTotal : integer ;
begin
// Generate a header
ss:= 'c:\binario\myfile.zip' ;
fBackupTitle := '' ;
fSizeTotal := 0 ;
fFilesTotal := 1 ;
try
SStr := TFilestream.create('c:\binario\teste1.txt', fmOpenRead or fmShareDenyNone);
fSizeTotal := fSizeTotal + SStr.Size;
finally
SStr.free;
end;
TStr := TFilestream.create(ss, fmCreate);
TStr.seek(0, 0);
L := length(fBackupTitle);
TStr.writeBuffer(L, sizeof(L)); //Size of title
TStr.writeBuffer(PChar(fBackupTitle)^,L); //title
TStr.writeBuffer(fSizeTotal, sizeof(fSizeTotal)); //Total Size of backup
TStr.writeBuffer(fFilesTotal, sizeof(fFilesTotal)); //Total file count
CurrentFile := 'c:\binario\teste1.txt';
L := length(CurrentFile);
TStr.writeBuffer(L, sizeof(L)); //Size of file name
TStr.writeBuffer(PChar(CurrentFile)^,L); //file name
try
SStr := TFilestream.create(Currentfile, fmOpenRead or fmShareDenyNone);
FA := FileGetDate(SStr.handle);
TStr.writeBuffer(FA, sizeof(FA)); //file age
TStr.WriteBuffer(FSignature, SizeOf(FSignature)); //new signature "EC2" in ver 2.00!
finally
SStr.free;
end;
TStr.free ;
end;

// Delphi code to read the file
procedure TForm1.Button2Click(Sender: TObject);
var S, Source : String ;
SStr: TStream;
L, FA, fSizeTotal, fFilesTotal : integer ;
Sig: array[0..3] of Char;
begin
// Read the header
lb.Items.Clear ;
source := 'c:\binario\myfile.zip' ;
if not Fileexists(Source) then exit;
SStr := TFilestream.create(Source, fmOpenRead or fmShareDenyNone);
SStr.seek(0,0);
SStr.readbuffer(L, sizeof(L));
lb.Items.Add('Length of title: ' + inttostr(L)) ;
SetString(S, PChar(nil), L);
SStr.ReadBuffer(PChar(S)^,L); //Title
lb.Items.Add('Title: ' + S) ;
SStr.readbuffer(fSizeTotal, sizeof(fSizeTotal));
lb.Items.Add('SizeTotal: ' + inttostr(fSizeTotal)) ;
SStr.readbuffer(fFilesTotal, sizeof(fFilesTotal));
lb.Items.Add('FilesTotal: ' + inttostr(fFilesTotal)) ;
SStr.readbuffer(L, sizeof(L)); // File size
lb.Items.Add('File size: ' + inttostr(L)) ;
SetString(S, PChar(nil), L);
SStr.ReadBuffer(PChar(S)^,L); //File name
lb.Items.Add('File name: ' + S) ;
// Read file.
SStr.ReadBuffer(FA, sizeof(FA)); //File age
lb.Items.Add('File age: ' + inttostr(FA)) ;
SStr.ReadBuffer(Sig, SizeOf(FSignature));
lb.Items.Add('Signature: ' + Sig) ;
sstr.Free ;
end;

// Java code to generate a file
public static void main(String[] args) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream() ;
DataOutputStream dout = new DataOutputStream(bout) ;
File f = new File("c://binario//teste1.txt") ;

String fBackupTitle = "" ;
int L = fBackupTitle.length() ;
dout.writeInt(L) ;
dout.write(fBackupTitle.getBytes()) ;

Long ltmp = new Long(f.length()) ;
int fSizeTotal = ltmp.intValue() ;
dout.writeInt(fSizeTotal) ;

int totalfiles = 1 ;
dout.writeInt(totalfiles) ;

String CurrentFile = "c:\\binario\\teste1.txt" ;
L = CurrentFile.length() ;
dout.writeInt(L) ;
dout.write(CurrentFile.getBytes()) ;

f = new File("c://binario//teste1.txt") ;
long modifiedTime = f.lastModified() ;
dout.writeLong(modifiedTime) ;

String FSignature = "EC2" ;
dout.write(FSignature.getBytes()) ;

dout.flush() ;
f = new File("c://binario//teste_int.zip") ;
FileOutputStream fout = new FileOutputStream(f) ;
fout.write(bout.toByteArray()) ;
fout.flush();
fout.close();
}



// Java code to read the file
public static void main(String[] args) throws IOException {
File f = new File("c://binario//teste_int.zip") ;
RandomAccessFile raf = new RandomAccessFile(f, "r");
raf.seek(0) ;

int L = raf.readInt();
System.out.println("L: " + L);
byte[] tmp = new byte[L] ;
raf.read(tmp) ;
String fBackupTitle = new String(tmp);
System.out.println("fBackupTitle: " + fBackupTitle);

int fSizeTotal = raf.readInt();
System.out.println("fSizeTotal: " + fSizeTotal);

int totalfiles = raf.readInt() ;
System.out.println("totalfiles: " + totalfiles);

L = raf.readInt() ;
System.out.println("CurrentFile.length : " + L);

tmp = new byte[L] ;
raf.read(tmp) ;
String CurrentFile = new String(tmp);
System.out.println("CurrentFile: " + CurrentFile);
long modifiedTime = raf.readLong();
System.out.println("modifiedTime: " + modifiedTime);

tmp = new byte[3] ;
raf.read(tmp) ;
String FSignature = new String(tmp);
System.out.println("FSignature: " + FSignature);
raf.close() ;
}
Kevin Dean [TeamB]
2005-04-04 16:41:32 UTC
Permalink
Hi all !! My name is Ronaldo. I4m from Brazil.
Im having a hard time on reading a file generated by a Software
created through Delphi, its not a regular text file, though it is a
file that was generated by a component, which main goal is to
compress any file using a Zlib, and then to save the bytes from that
compressed file as binary fields. That was just a brief introduction
so as you can have an idea of the general issue My real problem is
reading the header and the footer generated by that component (I do
not have any problem in reading and decompressing the data compressed
with Zlib). At that header, there is information, such as backup
title, size of the backup title, total bytes from the original file,
total files in backup, the size in bytes of the path + name of the
file that was compressed, path + name of the file compressed, date &
time of last update on that file, and a signature EC2 or ECS,
where the first one indicates that the content is compressed, and the
second one indicates that is not The component writes some data with
more frequency; if I manage to read those, I think Ill be able of
reading the others. I created a Delphi code very simple in order to
generate that header, and another one, to read it. I did the same in
Java. However, what I generate in Delphi, cannot be read in Java, and
vice versa. Im going to leave here the source codes in Java and
Delphi, in case someone can help me out. Probably somebody already
passed through this issue, or at least knows both languages.
I appreciate your help in advance, and apologize for the size of this message.
Without going into your code in too much detail, I would guess that the
problem you're experiencing is byte order. Delphi is Intel-based and
so writes/reads the low byte first; Java is platform-independent and
writes/reads the high byte first.

I strongly suggest that if you're trying to write code to read a ZIP
file that you start with a known good ZIP file, run it through the
Delphi and Java readers, and determine which one breaks. Creating a
file with one language and reading it with another doesn't tell you
which one is at fault; you need the independent arbiter of a known good
ZIP file.
--
Kevin Dean [TeamB]
Dolphin Data Development Ltd.
http://www.datadevelopment.com/

NEW WHITEPAPERS
Team Development with JBuilder and Borland Enterprise Server
Securing Borland Enterprise Server
http://www.datadevelopment.com/papers/index.html

Please see Borland's newsgroup guidelines at
http://info.borland.com/newsgroups/guide.html
Ronaldo
2005-04-05 12:35:42 UTC
Permalink
Dear Kevin.
Then I have a serious possession.
Because the application developed in Delphi uses a format proprietor to record the header, and my problem is exactly to read this header, the compacted data I am not having problem with them, it is enough to ignore the data of the header. But I need to read that header with Java to manipulate the data that were migrated of a legated system, that they are not compacted, but they were recorded with that header. A solution not very elegant it would be to write a .SO in Kylix that makes that work, but I would like to implement a solution purely Java.

I appreciate your help in advance,

Ronaldo.
Post by Kevin Dean [TeamB]
Hi all !! My name is Ronaldo. I4m from Brazil.
Im having a hard time on reading a file generated by a Software
created through Delphi, its not a regular text file, though it is a
file that was generated by a component, which main goal is to
compress any file using a Zlib, and then to save the bytes from that
compressed file as binary fields. That was just a brief introduction
so as you can have an idea of the general issue My real problem is
reading the header and the footer generated by that component (I do
not have any problem in reading and decompressing the data compressed
with Zlib). At that header, there is information, such as backup
title, size of the backup title, total bytes from the original file,
total files in backup, the size in bytes of the path + name of the
file that was compressed, path + name of the file compressed, date &
time of last update on that file, and a signature EC2 or ECS,
where the first one indicates that the content is compressed, and the
second one indicates that is not The component writes some data with
more frequency; if I manage to read those, I think Ill be able of
reading the others. I created a Delphi code very simple in order to
generate that header, and another one, to read it. I did the same in
Java. However, what I generate in Delphi, cannot be read in Java, and
vice versa. Im going to leave here the source codes in Java and
Delphi, in case someone can help me out. Probably somebody already
passed through this issue, or at least knows both languages.
I appreciate your help in advance, and apologize for the size of this message.
Without going into your code in too much detail, I would guess that the
problem you're experiencing is byte order. Delphi is Intel-based and
so writes/reads the low byte first; Java is platform-independent and
writes/reads the high byte first.
I strongly suggest that if you're trying to write code to read a ZIP
file that you start with a known good ZIP file, run it through the
Delphi and Java readers, and determine which one breaks. Creating a
file with one language and reading it with another doesn't tell you
which one is at fault; you need the independent arbiter of a known good
ZIP file.
--
Kevin Dean [TeamB]
Dolphin Data Development Ltd.
http://www.datadevelopment.com/
NEW WHITEPAPERS
Team Development with JBuilder and Borland Enterprise Server
Securing Borland Enterprise Server
http://www.datadevelopment.com/papers/index.html
Please see Borland's newsgroup guidelines at
http://info.borland.com/newsgroups/guide.html
Kevin Dean [TeamB]
2005-04-05 15:19:49 UTC
Permalink
Post by Ronaldo
Because the application developed in Delphi uses a format proprietor
to record the header, and my problem is exactly to read this header,
the compacted data I am not having problem with them, it is enough to
ignore the data of the header. But I need to read that header with
Java to manipulate the data that were migrated of a legated system,
that they are not compacted, but they were recorded with that header.
A solution not very elegant it would be to write a .SO in Kylix that
makes that work, but I would like to implement a solution purely Java.
Reading binary files is always tricky. The first thing you should do
is determine whether or not you are in the right place in the file.
After reading each field with Delphi, print out the current file
position. Do the same in Java. If the output differs, then you're
reading the wrong number of bytes.

Once you have the file positions lined up, then output the fields
themselves in Delphi and in Java. Typically your integers will be
different, and that can be resolved in Java by reading one byte at a
time. Assuming that the number stored is a 32-bit integer:

int result = 0;

for (int index = 0; index < 4; index++) {
// Bytes are high-order first, so shift the result by one byte.
result <<= 8;
// Add (through bitwise OR) the next byte.
result |= s.readByte();
}
--
Kevin Dean [TeamB]
Dolphin Data Development Ltd.
http://www.datadevelopment.com/

NEW WHITEPAPERS
Team Development with JBuilder and Borland Enterprise Server
Securing Borland Enterprise Server
http://www.datadevelopment.com/papers/index.html

Please see Borland's newsgroup guidelines at
http://info.borland.com/newsgroups/guide.html
Loading...