Reputation: 2092
I've generated a binary file from JAVA:
RandomAccessFile out = new RandomAccessFile(file, "rwd");
out.writeLong(calendar.getTimeInMillis());
out.writeDouble(double1);
out.writeDouble(double2);
out.writeDouble(double3);
How can I read this information from Delphi 2007?
I've tried something like this:
type TData = record
time: TDateTime;
double1: double;
double2: double;
double3: double;
end;
var
data: TData;
F : file of TData;
begin
AssignFile(F,fileName) ;
Reset(F) ;
Read (F, data);
...
but the values of time, double1, double2 and double3 are completly different.
Upvotes: 2
Views: 780
Reputation: 2092
Finally the solution is:
function Swap8ToDouble(A:double): double;
var
hold:double;
asm
mov edx,dword ptr[A]
mov ecx,dword ptr[A+4]
bswap edx
bswap ecx
mov dword ptr [hold],ecx
mov dword ptr [hold+4],edx
fld hold;
end;
function Int64Swap(A: int64): int64;
asm
mov edx,dword ptr [A]
mov eax,dword ptr [A+4]
bswap edx
bswap eax
end;
type TData = record
time: Int64;
double1: double;
double2: double;
double3: double;
end;
...
data.time := UnixToDateTime(Int64Swap(data.time) div 1000);
data.double1 := Swap8ToDouble(data.double1);
data.double2 := Swap8ToDouble(data.double2);
data.double3 := Swap8ToDouble(data.double3);
Upvotes: 2
Reputation: 613053
There are two issues here.
TDateTime
.Assuming you are going to change the Delphi code rather than the Java code, here's what you would do to bring the two sides together:
TDateTime
which measures days elapsed since the Delphi epoch.Dealing with endianness is simple enough, albeit rather tiresome.
The time conversion is perhaps a little more involved. The key information is that the Java epoch is the same as the Unix epoch. So a function that converts Unix time to Delphi TDateTime
is all you need. Fortunately the Delphi RTL supplies the very function. It's in the DateUtils
unit and is named UnixToDateTime
. Note that UnixToDateTime
receives a Unix time measured in seconds so you'll need to divide your value in milliseconds by 1000
.
One other point that I would make is that the Java code writes the data out with no gaps between fields. But the Delphi code uses an aligned record. Now, since all the members are the same size, there is no padding in this case. But it's something to watch out for. If I were you I would not be using legacy Pascal I/O to read this. I'd use a binary reader class that operates in a similar way to your Java writer. And I'd use that reader to read in the fields one at a time.
There may be something to be gained from finding (or writing) a reader class that handles the endian conversion for you.
Upvotes: 2
Reputation: 17203
Your primary logic is OK but, since you're writing and reading binary data, you have to maintain DataType compatibility between the writer and the reader, and you also have to take endianness of writer and reader.
The java calendar.getTimeInMillis()
returns a long
, the Delphi equivalent is Int64
, whereas Double is equivalent in both (64 bit IEEE), so your record should look like this:
type TData = record
Millis: Int64;
double1: double;
double2: double;
double3: double;
end;
Upvotes: 0
Reputation: 1201
calendar.getTimeInMillis() returns a long.
Your best bet if using delphi 7+ is a UInt64 to match java long
See here for java primitive datatypes descriptions and try to match to delphi datatypes
edit : As David Heffernan noticed you'll also have to convert endianness
Upvotes: 3