我们有两个团队,Delphi 团队和 Java 团队。 Delphi基于Delphi 11中的
TExtended80Rec
,存储在sqlite数据库中,并保存为二进制流。我尝试过使用Java来解析流中的内容,发现了几个困难
Delphi 字节:
[51, 51, 51215240114205, 29, 64]
Java 字节:
[52, 51, 51, 51, 51, -41, -16, 114, -51, 29, 64]
如何将这些流解析回
BigDecimal
类型
我希望得到您的帮助
public static void main(String[] args) {
// 从 Delphi 11 中获取的 10 字节的 Extended 类型字节数组
byte[] delphiBytes = {52, 51, 51, 51, -41, -16, 114, -51, 29, 64};
// 解析 Delphi 11 Extended 类型为 Java double
BigDecimal parsedValue = parseDelphiExtended(delphiBytes);
// 打印结果
System.out.println("解析后的值: " + parsedValue);
}
private static BigDecimal parseDelphiExtended(byte[] delphiBytes) {
// 解析符号位
boolean isNegative = (delphiBytes[0] & 0x80) != 0;
// 解析指数位
short exponent = (short) (((delphiBytes[1] & 0xFF) << 8) | (delphiBytes[2] & 0xFF));
int adjustedExponent = exponent - 16383;
// 解析尾数位
BigDecimal fraction = calculateFraction(delphiBytes);
// 计算 BigDecimal 类型的值
BigDecimal parsedValue = BigDecimal.valueOf(Math.pow(-1, isNegative ? 1 : 0) * Math.pow(2, adjustedExponent) * fraction.doubleValue());
return parsedValue;
}
private static BigDecimal calculateFraction(byte[] delphiBytes) {
// 解析尾数位
long mantissa = 0;
for (int i = 3; i < delphiBytes.length; i++) {
mantissa = (mantissa << 8) | (delphiBytes[i] & 0xFF);
}
// 构建 BigDecimal 类型的尾数
BigDecimal fraction = new BigDecimal(mantissa).divide(BigDecimal.valueOf(2).pow(64));
return fraction;
}
符号位:符号位是通过将最后一个字节值与十六进制数 $80 进行比较来确定的。
指数:提取十六进制最后2个字节的十进制值。
尾数:以十六进制计算剩余字节的十进制值,并将其乘以2的63次方。
最终值通过以下公式获得:符号位 * 尾数 * 2^(指数 - 16383) / 2^63。另外,通过添加 0.0000001 来进行精度处理。然后将生成的数值格式化为排除小数点后的尾随零,包括连续的零对及其他零。