Writing Long from Java to a file and reading it in C ++

I want to create a file containing exactly 8 bytes representing an unsigned long number. The file is created using Java and then read by C ++. So Java creates a file:

import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; public class Writer { public static void main(String[] args) throws Exception { ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); buffer.putLong(12345); ByteArrayOutputStream stream = new ByteArrayOutputStream(); stream.write(buffer.array()); try (FileOutputStream outputStream = new FileOutputStream("myFile")) { outputStream.write(stream.toByteArray()); } } } 

And here is how C ++ reads:

 #include <iostream> #include <vector> #include <fstream> #include <stdio.h> using namespace std; // I use this to get each byte from a file static std::vector<char> ReadAllBytes(char const* filename) { std::ifstream ifs(filename, ios::binary|ios::ate); std::ifstream::pos_type pos = ifs.tellg(); std::vector<char> result(pos); ifs.seekg(0, ios::beg); ifs.read(&result[0], pos); return result; } int main (int argc, char* argv[]) { std::vector<char> bytes = ReadAllBytes("myFile"); std::vector<char>::iterator it = bytes.begin(); char longBytes[8]; std::copy(&(*it), &(*it) + 8, longBytes); unsigned long value = *((unsigned long*)longBytes); std::cout << "Size: " << value; } 

The expected output is 12345 , but instead I get 4120793659044003840 .

I'm not sure if I did it wrong in Java or C ++. Or both. What was I supposed to do?

+7
java c ++ long-integer
source share
2 answers

Java writes long in "network order", which is a big argument. C ++ reads in hardware, which in your case is not enough endian.

This does not mean that your C ++ program must flip the bytes for conversion, because in this case it will fail on the hardware with a large order.

C provides a special group of functions for platform-independent data conversion to and from network order. You need to use the htonll function, which converts eight bytes in network order to your hardware order.

+10
source share

Java writes long as bytes encoded at the large end, guaranteed.

C ++ reads bytes, and on your computer (it is assumed that this is Intel x86) they are interpreted as low-value as a whole. (Big end on Motorola 68k and others.)

One solution to your problem is to manually recover an integer in C ++ in a portable way:

 uint64_t value = (uint64_t)(b[0] & 0xFF) << 56 | (uint64_t)(b[1] & 0xFF) << 48 | (uint64_t)(b[2] & 0xFF) << 40 | (uint64_t)(b[3] & 0xFF) << 32 | (uint64_t)(b[4] & 0xFF) << 24 | (uint64_t)(b[5] & 0xFF) << 16 | (uint64_t)(b[6] & 0xFF) << 8 | (uint64_t)(b[7] & 0xFF) << 0; 

Side note: your Java code can be simplified:

 DataOutputStream out = new DataOutputStream(new FileOutputStream("myFile")); try { out.writeLong(12345); // 8 bytes in big endian } finally { out.close(); } 
+7
source share

All Articles