JavaScript class that provides methods to read byte stream written in Delphi. Supports Delphi Simple types, ShortString and TDateTime. Data types Real48 and Extended are not implemented.
Note: JS doesn't support as big 64-bit integers as Delphi. To read those big values, use readInt64Precise() or readUInt64Precise(). Both methods return BigInt object.
Note: When reading a record you may need to read some extra bytes because of field alignments. Use packed records to avoid this.
type
TExampleRec = record
b1: byte;
b2: byte;
b3: byte;
Last: double;
end;
TPackedRec = packed record
b1: byte;
b2: byte;
b3: byte;
Last: double;
end;
procedure WriteTestBytes();
var
FS: TStream;
iInteger: Integer;
fDouble: Double;
bBoolean: boolean;
iInt64: Int64;
sShortString: ShortString;
sString10: String[10];
charA: array[1..20] of Char;
Rec: TExampleRec;
PackedRec: TPackedRec;
dtDateTime: TDateTime;
begin
FS := TFileStream.Create('D2JSDemo.bin', fmCreate or fmShareExclusive) ;
try
sShortString := 'PI as a whole number is:';
FS.Write(sShortString, SizeOf(sShortString));
iInteger := 3;
FS.Write(iInteger, SizeOf(Integer));
sShortString := 'and the decimal part:';
FS.Write(sShortString, SizeOf(sShortString));
fDouble := 0.1415926535;
FS.Write(fDouble, SizeOf(fDouble));
FillChar(charA, SizeOf(charA), 0);
charA[1] := 'T';
charA[2] := 'r';
charA[3] := 'u';
charA[4] := 'e';
charA[5] := '?';
FS.Write(charA, SizeOf(charA));
bBoolean := True;
FS.Write(bBoolean, SizeOf(bBoolean));
sShortString := 'Int64 and UInt64:';
FS.Write(sShortString, SizeOf(sShortString));
iInt64 := High(iInt64);
FS.Write(iInt64, SizeOf(iInt64));
FS.Write(iInt64, SizeOf(iInt64));
sString10 := '1234567890';
sString10 := 'Record:';
FS.Write(sString10, SizeOf(sString10));
Rec.b1 := 12;
Rec.b2 := 34;
Rec.b3 := 56;
Rec.Last := -987.65;
FS.Write(Rec, SizeOf(Rec));
sString10 := 'Packed:';
FS.Write(sString10, SizeOf(sString10));
PackedRec.b1 := 12;
PackedRec.b2 := 34;
PackedRec.b3 := 56;
PackedRec.Last := -987.65;
FS.Write(PackedRec, SizeOf(PackedRec));
dtDateTime := EncodeDateTime(2019, 11, 15, 17, 20, 27, 789);
FS.Write(dtDateTime, SizeOf(dtDateTime));
dtDateTime := -1.25; // 1899-12-29 06:00
FS.Write(dtDateTime, SizeOf(dtDateTime));
finally
FS.Free ;
end;
end;
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="DelphiByteStreamReader-JS2020.js"></script>
<script type="text/javascript">
function readByteStream(filePath) {
let fileReader = new FileReader();
if (filePath.files && filePath.files[0]) {
fileReader.onload = function(e) {
let output = e.target.result;
let reader = new DelphiByteStreamReader(output);
let e1 = reader.readShortString(); // "PI as a whole number is:"
let e2 = reader.readInteger(); // 3
let e3 = reader.readShortString(); // "and the decimal part:"
let e4 = reader.readDouble(); // 0.1415926535
let e5 = reader.readCharArray(20); // "True?"
let e6 = reader.readBoolean(); // true
let e7 = reader.readShortString(); // "Int64 and UInt64:"
let e8 = reader.readInt64(); // 9223372036854776000
let e9 = reader.readInt64Precise(); // 9223372036854775807n
let s1 = reader.readShortString(10); // "Record:"
let rec1 = {};
rec1.b1 = reader.readByte(); // 12
rec1.b2 = reader.readByte(); // 34
rec1.b3 = reader.readByte(); // 56
reader.incOffset(5); // Delphi alignment
rec1.last = reader.readDouble(); // -987.65
let s2 = reader.readShortString(10); // "Packed:"
let rec2 = {};
rec2.b1 = reader.readByte(); // 12
rec2.b2 = reader.readByte(); // 34
rec2.b3 = reader.readByte(); // 56
rec2.last = reader.readDouble(); // -987.65
let d1 = reader.readDateTime(); // d1.toISOString() "2019-11-15T17:20:27.789Z"
let d2 = reader.readDateTime(); // d2.toISOString() "1899-12-29T06:00:00.000Z"
};
fileReader.readAsArrayBuffer(filePath.files[0]);
}
}
</script>
</head>
<body>
<input type="file" onchange='readByteStream(this)' />
</body>
</html>