Rayz
Rayz

Reputation: 533

Java reads wrong values from binary structured file

I have a file which consist of Delphi records. The record looks like:

TPoint = record
    X, Y: Double;
end;

As I know Delphi stores data as LittleEndian, and Java as BigEndian so the read method looks like:

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);
}

Everything seemed to be fine but sometimes I take the corrupted data. I got

638 offset: 10256   Point{x=3.143E-319, y=48.47134}

But should to get

638 offset: 10256   Point{x=22.25315, y=48.47134}

When I opened the file and look the data with offset 10256 I see:

7F FB 3A 70 CE 40 36 40

which is 22.25315 in LittleEndian. So i wondered what is the problem? Is there any problem with Long.reverseBytes() method? Or it's impossible to convert any doubles from LE to BE and vice versa?

Upvotes: 1

Views: 279

Answers (2)

Rayz
Rayz

Reputation: 533

Have found the bug. Instead of

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

just needed to read as follows:

Long.reverseBytes(in.readLong())

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500535

I suspect the problem may be because you're reading 8 bytes as a big-endian double when they're not a big-endian double. Given that bits have specific meanings in double, that could cause problems - Java may be normalizing NaN values, for example. It's a bit like reading text data using an encoding that you know is incorrect, and then converting it back into bytes...

If you read the value as a long to start with, that should preserve all the bits, so you can reverse the bytes and then convert to a double:

double x = Double.longBitsToDouble(Long.reverseBytes(in.readLong()));
double y = Double.longBitsToDouble(Long.reverseBytes(in.readLong()));

Upvotes: 4

Related Questions