我已经从JAVA生成了一个二进制文件:
RandomAccessFile out = new RandomAccessFile(file, "rwd");
out.writeLong(calendar.getTimeInMillis());
out.writeDouble(double1);
out.writeDouble(double2);
out.writeDouble(double3);
如何从Delphi 2007中读取此信息?
我尝试过这样的事情:
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);
...
但是time,double1,double2和double3的值完全不同。
答案 0 :(得分:3)
calendar.getTimeInMillis()返回一个长。
如果使用delphi 7+是一个匹配java long
的UInt64,最好的选择有关java原始数据类型的描述,请参阅here并尝试匹配delphi数据类型
编辑:正如David Heffernan注意到你还必须转换字节序
答案 1 :(得分:2)
这里有两个问题。
TDateTime
。假设您要更改Delphi代码而不是Java代码,那么您可以采取以下措施将双方联系起来:
TDateTime
,它测量自德尔福纪元以来的几天。处理字节序很简单,虽然相当无聊。
时间转换可能更多一些。关键信息是Java纪元与Unix纪元相同。因此,您只需要一个将Unix时间转换为Delphi TDateTime
的函数。幸运的是,Delphi RTL提供了非常好的功能。它位于DateUtils
单元中,名为UnixToDateTime
。请注意UnixToDateTime
接收以秒为单位测量的Unix时间,因此您需要将您的值除以1000
为单位。
我要做的另一点是Java代码将数据写出来,字段之间没有间隙。但Delphi代码使用对齐记录。现在,由于所有成员的大小相同,因此在这种情况下没有填充。但值得注意的是。如果我是你,我不会使用传统的Pascal I / O来阅读它。我将使用二进制阅读器类,其操作方式与Java编写器类似。我会用那个读者一次一个地阅读这些字段。
找到(或编写)为您处理endian转换的reader类可能会有所收获。
答案 2 :(得分:2)
最后解决方案是:
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);
答案 3 :(得分:0)
您的主要逻辑是正常的,但是,由于您正在编写和读取二进制数据,您必须保持编写器和阅读器之间的DataType兼容性,并且还必须采用编写器和阅读器的字节序。
java calendar.getTimeInMillis()
返回long
,Delphi等效于Int64
,而Double在两者中都是等效的(64位IEEE),因此您的记录应如下所示:
type TData = record
Millis: Int64;
double1: double;
double2: double;
double3: double;
end;