У меня есть файл, который состоит из записей Delphi. Запись выглядит так:
TPoint = record
X, Y: Double;
end;
Поскольку я знаю, что Delphi хранит данные как LittleEndian, а Java как BigEndian, так что метод чтения выглядит так:
public Point readPoint() throws IOException {
double x = Double.longBitsToDouble(
Long.reverseBytes(
Double.doubleToLongBits(in.readDouble()
)
)
);
double y = Double.longBitsToDouble(
Long.reverseBytes(
Double.doubleToLongBits(in.readDouble()
)
)
);
return new Point(x, y);
}
Все казалось прекрасным, но иногда я беру испорченные данные. я получил
638 offset: 10256 Point{x=3.143E-319, y=48.47134}
Но нужно
638 offset: 10256 Point{x=22.25315, y=48.47134}
Когда я открыл файл и посмотрел данные со смещением 10256, я вижу:
7F FB 3A 70 CE 40 36 40
что составляет 22.25315 в LittleEndian. Поэтому я задавался вопросом, в чем проблема? Есть ли проблема с методом Long.reverseBytes()? Или невозможно преобразовать любые удвоения из LE в BE и наоборот?
Я подозреваю, что проблема может заключаться в том, что вы читаете 8 байтов в качестве двунаправленного double
если они не являются двунаправленными. Учитывая, что биты имеют определенные значения в double
, это может вызвать проблемы. Например, Java может нормализовать значения NaN. Это немного похоже на чтение текстовых данных с использованием кодировки, которая, как вы знаете, неверна, а затем преобразование ее обратно в байты...
Если вы прочтете значение как long
нужно начинать, это должно сохранить все биты, чтобы вы могли отменить байты, а затем преобразовать в double
:
double x = Double.longBitsToDouble(Long.reverseBytes(in.readLong()));
double y = Double.longBitsToDouble(Long.reverseBytes(in.readLong()));
Найди ошибку. Вместо
Long.reverseBytes(Double.doubleToLongBits(in.readDouble())
просто нужно было читать:
Long.reverseBytes(in.readLong())
Long.reverseBytes(in.readLong())
.