12

I have a binary file that I read byte by byte.

I come across a section that is 8 bytes long, holding a double precision float (little endian). I can't figure out how to read this in and calculate it properly with masking and/or casting.

(To be specific, the file type is .LAS, but that shouldn't matter).

Are there any Java tricks?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RedLeader
  • 657
  • 1
  • 15
  • 28

5 Answers5

21

You can use ByteBuffer

from a byte[] bytes

 double d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getDouble();

from a Socket

 ByteBuffer bb = ByteBuffer.allocate(64*1024).order(ByteOrder.LITTLE_ENDIAN );
 socket.read(bb);
 bb.flip();
 double d = bb.getDouble();
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Extremely solid contribution, exactly what I needed. Thank you (and to everyone else who replied so fast!) Have a good weekend. – RedLeader Jun 24 '11 at 17:15
  • a direct buffer would be better here (2nd sample), provided the buffer it's not allocated often and reused. In such cases I tend to use the socket readBuffer as size. – bestsss Jun 24 '11 at 17:26
  • @bestsss, Agreed that a direct ByteBuffer would be better if managed correctly. I have found direct buffers can be up to 20% faster. If you use it with the Unsafe class it can be another 30% faster. ;) – Peter Lawrey Jun 24 '11 at 17:32
  • non-direct (byte[] backed up) are actually copied from a ThreadLocal allocated ByteBuffer when read by a native file descriptor (socket/file) – bestsss Jun 24 '11 at 20:45
1

Two different approaches are described here: http://bytes.com/topic/java/answers/18253-big-endian-vs-little-endian-data. Both would work.

jtoberon
  • 8,706
  • 1
  • 35
  • 48
1

If you need to read and swap byte order, there is EndianUtils from Commons IO:

https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/EndianUtils.html

spieden
  • 1,239
  • 1
  • 10
  • 23
  • 1
    The link is broken (*"Not Found. The requested URL /proper/commons-io/api-release/org/apache/commons/io/EndianUtils.html was not found on this server."*). – Peter Mortensen Nov 17 '17 at 22:11
1
  1. Convert from little endian to big endian.
  2. Wrap your converted bytes in ByteBufferInputStream use.
  3. Get your double precision number via DataInputStream.readDouble(in).

Alternatively, you can just take the body of the readDouble method from JDK source and skip step 2 and 3.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alphazero
  • 27,094
  • 3
  • 30
  • 26
0

Just use a DataInputStream to read the file, and use the readDouble() method.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eric
  • 95,302
  • 53
  • 242
  • 374