0

I am attempting to convert a program that reads a binary file in C++ to java. The file is in little-endian.

fread(n, sizeof (unsigned), 1, inputFile);

The snippet above of c++ reads 1 integer into the integer variable 'n'.

I am currently using this method to accomplish the same thing:

public static int readInt(RandomAccessFile inputStream) throws IOException {
    int retVal;
    byte[] buffer = new byte[4];
    inputStream.readFully(buffer);
    ByteBuffer wrapped = ByteBuffer.wrap(buffer);
    wrapped.order(ByteOrder.LITTLE_ENDIAN);
    retVal = wrapped.getInt();
    return retVal;
}

but this method sometimes differs in its result to the c++ example. I haven't been able to determine which parts of the file cause this method to fail, but I know it does. For example, when reading one part of the file my readInt method returns 543974774 but the C++ version returns 1.

Is there a better way to read little endian values in Java? Or is there some obvious flaw in my implementation? Any help understanding where I could be going wrong, or how could I could read these values in a more effective way would be very appreciated.

Update: I am using RandomAcccessFile because I frequently require fseek functionality which RandomAccessFile provides in java

219CID
  • 340
  • 5
  • 15
  • I thought that was not useable because readInt reads an integer in big endian? – 219CID Dec 19 '20 at 23:55
  • 1
    Huh, yeah, absolutely true. – Konrad Rudolph Dec 20 '20 at 00:03
  • 1
    Are the values you are reading signed or unsigned? – tgdavies Dec 20 '20 at 00:12
  • The values are all unsigned. – 219CID Dec 20 '20 at 00:16
  • 2
    I think that you need to run both your Java and C++ programs, printing the values as you read them, along with the offset in the file, and then find the first point at which they differ. – tgdavies Dec 20 '20 at 00:16
  • 1
    Also, `unsigned` in C++ does not necessarily have to be 4 bytes. C++ is not Java, where the size of these types are fixed. To be sure, on the C++ side, use `int32_t` or `uint32_t`, not `unsigned`. – PaulMcKenzie Dec 20 '20 at 00:18
  • 1
    The values getInt returns are signed, so that may cause you problems. I suspect that your problem is not entirely with `readInt` but also with your positioning within the file. – tgdavies Dec 20 '20 at 00:19

1 Answers1

1

543974774 is, in hex, 206C6576.

There is no endianness on the planet that turns 206C6576 into '1'. The problem is therefore that you aren't reading what you think you're reading: If the C code is reading 4 bytes (or even a variable, unknown number of bytes) and turns that into '1', then your java code wasn't reading the same bytes - your C code and java code is out of sync: At some point, your C code read, for example, 2 bytes, and your java code read 4 bytes, or vice versa.

The problem isn't in your readInt method - that does the job properly every time.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Absolutely correct. Prior to reading the area which I thought was the problem I was fseeking to the wrong spot because I was reading an int as signed rather than unsigned. – 219CID Dec 20 '20 at 19:03