patternjavaMinor
Deserializing a byte array from Java in C++
Viewed 0 times
fromarraybytejavadeserializing
Problem
I am writing a byte array value into a file, consisting of up to three of these arrays, using Java with big Endian byte order format. Now I need to read that file from a C++ program.
I am writing
This writes the byte array value into a file with big Endian format:
Now I need to retrieve the byte array from that same file using this C++ program
short employeeId = 32767;
long lastModifiedDate = "1379811105109L";
byte[] attributeValue = os.toByteArray();I am writing
employeeId, lastModifiedDate and attributeValue together into a single byte array. I am writing that resulting byte array into a file and then I will have my C++ program retrieve that byte array data from the file and then deserialize it to extract employeeId, lastModifiedDate and attributeValue from it.This writes the byte array value into a file with big Endian format:
public class ByteBufferTest {
public static void main(String[] args) {
String text = "Byte Array Test For Big Endian";
byte[] attributeValue = text.getBytes();
long lastModifiedDate = 1289811105109L;
short employeeId = 32767;
int size = 2 + 8 + 4 + attributeValue.length; // short is 2 bytes, long 8 and int 4
ByteBuffer bbuf = ByteBuffer.allocate(size);
bbuf.order(ByteOrder.BIG_ENDIAN);
bbuf.putShort(employeeId);
bbuf.putLong(lastModifiedDate);
bbuf.putInt(attributeValue.length);
bbuf.put(attributeValue);
bbuf.rewind();
// best approach is copy the internal buffer
byte[] bytesToStore = new byte[size];
bbuf.get(bytesToStore);
writeFile(bytesToStore);
}
/**
* Write the file in Java
* @param byteArray
*/
public static void writeFile(byte[] byteArray) {
try{
File file = new File("bytebuffertest");
FileOutputStream output = new FileOutputStream(file);
IOUtils.write(byteArray, output);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}Now I need to retrieve the byte array from that same file using this C++ program
Solution
Obviously the code isn't portable to big-endian machines. I'll use C syntax, since I'm more familiar with that than C++.
If you have
Why not read directly into the values:
Since you can manipulate pointers in C, you just need to provide a universal pointer (
Using this Java test code:
The output from this code is:
You can read the values in with this C code:
I compiled this on Ubuntu x64 with clang. Its output was:
Keep in mind that the only unsigned types in Java are
If you have
endian.h, you can use the functions in there; if not, you should have arpa/inet.h which defines functions for swapping network byte order (big-endian) to host byte order, but lacks a function for 64-bit values. Look for either be16toh (from endian.h) or ntohs (from arpa/inet.h) and friends.Why not read directly into the values:
fread((void *)&employeeId, sizeof(employeeId), 1, file);
employeeId = be16toh(employeeId);Since you can manipulate pointers in C, you just need to provide a universal pointer (
void *) to the read function where it should place the results. The & operator takes the address of a value. Once that is done, you can manipulate the value directly, as above.Using this Java test code:
import java.io.*;
public class write {
public static void main(String... args) throws Exception {
final FileOutputStream file = new FileOutputStream("java.dat");
final DataOutputStream data = new DataOutputStream(file);
final long time = System.currentTimeMillis();
final short value = 32219;
// fill a table with a..z0..9
final byte[] table = new byte[36];
int index = 0;
for (int i = 0; i < 26; i++) {
table[index++] = (byte)(i + 'a');
}
for (int i = 0 ; i < 10; i++) {
table[index++] = (byte)(i + '0');
}
data.writeLong(time);
data.writeShort(value);
data.writeInt(table.length);
data.write(table);
data.close();
System.out.format("wrote time: %d%n value: %d%n length: %d%n table:%n", time, value, table.length);
for (int i = 0; i < table.length; i++) {
System.out.format("%c ", (char)table[i]);
}
System.out.println();
}
}The output from this code is:
wrote time: 1380743479723
value: 32219
length: 36
table:
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9You can read the values in with this C code:
#include
#include
#include
#include
int main(int argc, char **argv) {
int64_t time;
int16_t value;
int32_t length;
u_int8_t *array;
FILE *in = fopen("java.dat", "rb");
fread(&time, sizeof(time), 1, in);
time = (int64_t)be64toh( (u_int64_t)time);
fread(&value, sizeof(value), 1, in);
value = (int16_t)be16toh( (u_int16_t)value );
fread(&length, sizeof(length), 1, in);
length = (int32_t)be32toh( (u_int32_t)length );
array = (u_int8_t *)malloc(length);
fread(array, sizeof(array[0]), length, in);
fclose(in);
printf("time: %ld\nvalue: %d\narray length: %d\narray:\n", time, value, length);
for (int i = 0; i < length; i++) {
printf("%c ", array[i]);
}
printf("\n");
free(array);
return 0;
}I compiled this on Ubuntu x64 with clang. Its output was:
./a.out
time: 1380743479723
value: 32219
array length: 36
array:
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9Keep in mind that the only unsigned types in Java are
byte (8 bits) and char (16-32 bits).Code Snippets
fread((void *)&employeeId, sizeof(employeeId), 1, file);
employeeId = be16toh(employeeId);import java.io.*;
public class write {
public static void main(String... args) throws Exception {
final FileOutputStream file = new FileOutputStream("java.dat");
final DataOutputStream data = new DataOutputStream(file);
final long time = System.currentTimeMillis();
final short value = 32219;
// fill a table with a..z0..9
final byte[] table = new byte[36];
int index = 0;
for (int i = 0; i < 26; i++) {
table[index++] = (byte)(i + 'a');
}
for (int i = 0 ; i < 10; i++) {
table[index++] = (byte)(i + '0');
}
data.writeLong(time);
data.writeShort(value);
data.writeInt(table.length);
data.write(table);
data.close();
System.out.format("wrote time: %d%n value: %d%n length: %d%n table:%n", time, value, table.length);
for (int i = 0; i < table.length; i++) {
System.out.format("%c ", (char)table[i]);
}
System.out.println();
}
}wrote time: 1380743479723
value: 32219
length: 36
table:
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9#include <stdio.h>
#include <stdlib.h>
#include <endian.h>
#include <sys/types.h>
int main(int argc, char **argv) {
int64_t time;
int16_t value;
int32_t length;
u_int8_t *array;
FILE *in = fopen("java.dat", "rb");
fread(&time, sizeof(time), 1, in);
time = (int64_t)be64toh( (u_int64_t)time);
fread(&value, sizeof(value), 1, in);
value = (int16_t)be16toh( (u_int16_t)value );
fread(&length, sizeof(length), 1, in);
length = (int32_t)be32toh( (u_int32_t)length );
array = (u_int8_t *)malloc(length);
fread(array, sizeof(array[0]), length, in);
fclose(in);
printf("time: %ld\nvalue: %d\narray length: %d\narray:\n", time, value, length);
for (int i = 0; i < length; i++) {
printf("%c ", array[i]);
}
printf("\n");
free(array);
return 0;
}./a.out
time: 1380743479723
value: 32219
array length: 36
array:
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9Context
StackExchange Code Review Q#32106, answer score: 4
Revisions (0)
No revisions yet.