Java читает неправильные значения из двоичного структурированного файла

1

У меня есть файл, который состоит из записей 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 и наоборот?

  • 1
    Почему вы читаете двойной для начала? Конечно, вам лучше использовать Long.reverseBytes(in.readLong()) .
  • 0
    Я должен согласиться. Если вы читаете двойное с байтами в неправильном порядке, возможно, что происходит некоторая нормализация, которая изменяет биты, прежде чем вы заставите их изменить их.
Показать ещё 1 комментарий
Теги:
file
structure
endianness

2 ответа

4
Лучший ответ

Я подозреваю, что проблема может заключаться в том, что вы читаете 8 байтов в качестве двунаправленного double если они не являются двунаправленными. Учитывая, что биты имеют определенные значения в double, это может вызвать проблемы. Например, Java может нормализовать значения NaN. Это немного похоже на чтение текстовых данных с использованием кодировки, которая, как вы знаете, неверна, а затем преобразование ее обратно в байты...

Если вы прочтете значение как long нужно начинать, это должно сохранить все биты, чтобы вы могли отменить байты, а затем преобразовать в double:

double x = Double.longBitsToDouble(Long.reverseBytes(in.readLong()));
double y = Double.longBitsToDouble(Long.reverseBytes(in.readLong()));
  • 0
    Спасибо за ответ. Это действительно решило проблему.
  • 1
    doubleToLongBits изменяет NaN определенно к каноническому представлению, его явно указано сделать это в Javadocs: docs.oracle.com/javase/8/docs/api/java/lang/...
1

Найди ошибку. Вместо

Long.reverseBytes(Double.doubleToLongBits(in.readDouble())

просто нужно было читать:

Long.reverseBytes(in.readLong())

Ещё вопросы

Сообщество Overcoder
Наверх
Меню