4

I have a well defined binary data and I want to write Java API for it.
The file format is like

File Signature     char[4]               4 bytes 
File Source ID     unsigned short        2 bytes
Header Size        unsigned long         4 bytes
Max                double                8 bytes

I am using DataInputStream for parsing the data. char is easy to parse, no problem. But unsigned cannot be parsed correctly.
I know Java has no unsigned number. How do I convert it? (Please take unsigned long as example).

EDIT

Here is the code I worte:

File file = new File("lidar.las");

DataInputStream in= new DataInputStream(new FileInputStream(file));

in.skipBytes(6);

long read = (long) (in.readInt() & 0xFFFFFFFFL);

System.out.println("read " + read);


the output is

read 3288596480

my expected number is 1220 .I do not know the code that wrote this binary record, probably in c. All I want is writing a Java version to read data out.

Solved
I am not sure I can answer my own question. LOL
Anyway, Here is the solutions.

private static int getSignedInt( final int unsignedInt ){

    ByteBuffer bb=ByteBuffer.allocate(1024*4);

    bb.putInt(unsignedInt).flip();

    int result =bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
    bb.clear();

    return  result;
}
Saddy
  • 313
  • 4
  • 22
  • Do you need to do some kind of math with them? And do you need an 8-byte unsigned integer? The sortof obvious answer is to read them in to signed integers, for example your 4-byte unsigned long fits in a Java long. – Radiodef Jan 12 '14 at 09:09
  • unsigned long is not going to be 4 bytes on any modern system. That aside, since Java offers a 8 byte signed long, that covers it. – Brian Roach Jan 12 '14 at 09:38

2 Answers2

2

Just read them as short (2 bytes - Java) and int (4 bytes - Java) in your
Java code. You will not lose any information. If you need to output them later,
do a conversion so that you don't output signed numbers.

Given their names: File Source ID and Header Size I doubt you
will do any arithmetic operations on them. If you do, be careful.

Alternatively, you can read them both in long (8 bytes in Java),
and not worry about arithmetic operations as they will not cause issues.

Alternatively, you can read your values as byte arrays in Java,
and then transform them to the proper types in your Java code.
This is probably the most explicit and clean solution.
But it requires more coding.

peter.petrov
  • 38,363
  • 16
  • 94
  • 159
  • 3
    To transform a signed int into an positive long in Java: long l = i & 0xFFFFFFFFL; – JB Nizet Jan 12 '14 at 09:14
  • @peter.petrov: sorry, reading it as long does not work, it give me negative. I am confused that long take 8 bytes but the header size is 4 bytes, Dose that mean I added 4 extra bytes? – Saddy Jan 12 '14 at 09:28
  • @Saddy_Grade Not sure what exactly you're trying but I suggest you read the 'File Source ID' and 'Header Size' are byte arrays. Then you construct long values from them. See here: http://stackoverflow.com/questions/1026761/how-to-convert-a-byte-array-to-its-numeric-value-java – peter.petrov Jan 12 '14 at 09:41
  • @peter.petrov: I used `readLong() & 0xFFFFFFFFL`. it give me positive, but not correct number. – Saddy Jan 12 '14 at 09:47
  • readLong() reads 8 bytes. Not just 4. If you want to read 4 bytes, then use readInt() and transform the result to a positive long using the bitmask. – JB Nizet Jan 12 '14 at 09:48
  • @Saddy_Grade No, no. Use readInt(), then do what JB Nizet mentioned. – peter.petrov Jan 12 '14 at 09:48
  • sorry guys, `long read = (long) (in.readInt() & 0xFFFFFFFFL);` is not the number that I want. the bitmask 0xFFFFFFFFL might wrong? Sorry I do not know much about bitmask – Saddy Jan 12 '14 at 10:06
  • @Saddy_Grade: now it's time to edit your question, post the code used to write and read the records, post example inputs and example outputs. – JB Nizet Jan 12 '14 at 10:24
2

DataInputStream reads bytes in Big Endian orientation, but check this out:

3288596480 = 0xC4040000

Reversing the bytes, you get 0x04C4 = 1220

You just have to read the values in Little Endian. The question about the sign turns out to be a red herring.

Hakanai
  • 12,010
  • 10
  • 62
  • 132
  • The way I usually deal with doubles when parsing binary is to use the existing method to read a long (which yes, you would reverse) and then call Double.longBitsToDouble to convert the long to a double. – Hakanai Jan 14 '14 at 04:04