1

I have a file on disk which I'm reading which has been written by c/c++ code. I know I have two 64-bit unsigned integers to read, but Java doesn't support unsigned integers, so the value I get when I do DataInputStream.readLong() is incorrect. (Ignore byte-order for now I'm actually using a derivative of DIS called LEDataInputStream which I downloaded from the web)

A lot of posts on here talk about using BigInteger but the javadoc for reading a bytearray only talks about loading a bytearray respresentation, and the questions seem centered on the fact that some people are going outside the positive bounds of the java long type, which I will be nowhere near with the data I'm reading.

I have a MATLab/Octave script which reads these long long values as two 32-bit integers each, then does some multiplying and adding to get the answer it wants too.

I suppose the question is - how do i read a 64-bit unsigned integer either using BigInteger, or using [LE]DataInputStream.XXX?

Thanks in advance

James Booker
  • 108
  • 1
  • 6

3 Answers3

3

I would suggest using a ByteBuffer and then using code such as this to get what you want.

Rich
  • 15,602
  • 15
  • 79
  • 126
  • This looks promising, but I need to implement the feature to read the long type myself (since there's no method there for reading an unsigned long) and put it into BigInteger. I've accepted this as the official answer as it is the closest to what I wanted – James Booker Feb 24 '11 at 12:22
1

You can use a long as a 64-bit value to store unsigned data. Here is a module showing that most Unsigned operations can be performed using the standard long type. It really depends on what you want to do with the value as whether this is problem or not.

EDIT: A common approach to handling unsigned numbers is to widen the data type. This simpler in many cases but not a requirement (and for long using BigInteger doesn't make things any simpler IMHO)

EDIT2: What is wrong with the following code?

long max_unsigned = 0xFFFFFFFFFFFFFFFFl;
long min_unsigned = 0;
System.out.println(Unsigned.asString(max_unsigned) + " > "
        + Unsigned.asString(min_unsigned) + " is "
        + Unsigned.gt(max_unsigned, min_unsigned));

prints

18446744073709551615 > 0 is true
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Unfortunately, this doesn't answer my query fully - the data I have is already on disk and not written by me, so I can't just use the signed java type, as when i read it from disk the absolute value is wrong! – James Booker Feb 24 '11 at 12:19
  • @James, But how is it wrong and can you do anything about it? I would say you can, without much complexity. IMHO, It only seems impossible because you haven't thought about it. – Peter Lawrey Feb 24 '11 at 14:17
  • @James, I have added an example that shows the values are not wrong. – Peter Lawrey Feb 24 '11 at 14:25
0

first you check out this question

Also see this

Now use of BigInteger class

// Get a byte array
byte[] bytes = new byte[]{(byte)0x12, (byte)0x0F, (byte)0xF0};

// Create a BigInteger using the byte array
BigInteger bi = new BigInteger(bytes);

// Format to binary
String s = bi.toString(2);      // 100100000111111110000

// Format to octal
s = bi.toString(8);             // 4407760

// Format to decimal
s = bi.toString();              // 1183728

// Format to hexadecimal
s = bi.toString(16);            // 120ff0
if (s.length() % 2 != 0) {
    // Pad with 0
    s = "0"+s;
}


// Parse binary string
bi = new BigInteger("100100000111111110000", 2);

// Parse octal string
bi = new BigInteger("4407760", 8);

// Parse decimal string
bi = new BigInteger("1183728");

// Parse hexadecimal string
bi = new BigInteger("120ff0", 16);

// Get byte array
bytes = bi.toByteArray();
Community
  • 1
  • 1
ayush
  • 14,350
  • 11
  • 53
  • 100