2

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 の値は完全に異なります。

4

4 に答える 4

3

calendar.getTimeInMillis() は long を返します。

Delphi 7+を使用している場合の最善の策は、Java longに一致するUInt64です

Java プリミティブ データ型の説明については、こちらを参照してください。デルファイのデータ型と一致するようにしてください。

編集:David Heffernanが気付いたように、エンディアンも変換する必要があります

于 2013-03-26T15:01:49.873 に答える
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);
于 2013-03-26T17:50:57.657 に答える
2

ここには 2 つの問題があります。

  1. Java はビッグ エンディアン、Delphi はリトル エンディアンです。
  2. Java コードは、日付を 64 ビット整数として書き込みます。Delphi コードは浮動小数点を読み取りますTDateTime

Java コードではなく Delphi コードを変更すると仮定すると、2 つの側面をまとめるには次のようにします。

  • エンディアンの問題に対処するためのヘルパー ユーティリティを検索または記述します。データを読み込んだら、すぐにビッグ エンディアンからリトル エンディアンに変換します。
  • 日付を 64 ビット整数として読み取ります。次に、Java エポックとは何かを調べ、Java エポックからのミリ秒数をTDateTime、Delphi エポックからの経過日数を測定する Delphi に変換する必要があります。

エンディアンを扱うのは簡単ですが、かなり面倒です。

時間の変換は、おそらくもう少し複雑です。重要な情報は、Java エポックが Unix エポックと同じであるということです。したがって、必要なのは Unix 時間を Delphi に変換する関数TDateTimeだけです。幸いなことに、Delphi RTL はまさにその機能を提供します。DateUtilsユニットにあり、名前が付けられていUnixToDateTimeます。秒単位で測定された Unix 時間を受け取ることに注意してください。そのUnixToDateTimeため、ミリ秒単位の値を で割る必要があります1000

もう 1 つ指摘しておきたいのは、Java コードはフィールド間に隙間なくデータを書き出すということです。しかし、Delphi コードは整列されたレコードを使用します。現在、すべてのメンバーが同じサイズであるため、この場合はパディングはありません。しかし、それは注意すべきことです。私があなただったら、これを読むために従来の Pascal I/O を使用しないでしょう。Javaライターと同様の方法で動作するバイナリリーダークラスを使用します。そして、そのリーダーを使用して、一度に 1 つずつフィールドを読み取ります。

エンディアン変換を処理するリーダー クラスを見つける (または作成する) ことから得られるものがあるかもしれません。

于 2013-03-26T15:02:49.167 に答える
0

プライマリ ロジックは問題ありませんが、バイナリ データの書き込みと読み取りを行っているため、ライターとリーダーの間で DataType の互換性を維持する必要があり、ライターとリーダーのエンディアンも取得する必要があります。

Javacalendar.getTimeInMillis()は a を返しますlong。Delphi に相当するものは ですがInt64、Double はどちらも (64 ビット IEEE) と同等であるため、レコードは次のようになります。

type TData = record
  Millis: Int64;
  double1: double;
  double2: double;
  double3: double;
end;
于 2013-03-26T15:03:24.060 に答える