7

I'm working on an encryption algorithm and I need to generate some information in Java (a binary file) to read in C++.

I'm not sure if the problem is how I create the binary file or how I read it, though I can perfectly read the information in Java.

So I made a simple test. In Java I save the number 9 to a binary file, and then I try to read it in C++, but it does not read a number.

Can someone please tell me how I can do this?

The Java code:

int x = 9;

        try{
            ObjectOutputStream salida=new ObjectOutputStream(new 
            FileOutputStream("test.bin"));
            salida.writeInt(x);
            salida.close();
            System.out.println("saved");
        } catch(Exception e){
            System.out.println(e);
        }

The C++ code:


streampos size;
  char * memblock;

  ifstream file ("test.bin", ios::in|ios::binary|ios::ate);
  if (file.is_open())
  {
    size = file.tellg();
    cout<< size << endl;
    memblock = new char [size];
    file.seekg (0, ios::beg);
    file.read (memblock, size);
    file.close();

    int i;
    for (i = 0; i < sizeof(memblock); i++)
    {
        cout << memblock[i] <<endl;
    }
 delete[] memblock;
  }
  else cout << "Unable to open file";

This is the output:

�
�


w
Boann
  • 44,932
  • 13
  • 106
  • 138
  • 1
  • 1
    [Here is a whole page full of ways to read a whole file of text data into a `string`](https://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring) I like answer 2 option 1. Note how it eliminates the need to manually allocate and manage any storage. – user4581301 Aug 30 '19 at 17:15

3 Answers3

4

Your problem is that you are using ObjectOutputStream to write the data. This encodes the object graph in a Java-specific form intended to be read with ObjectInputStream. To make the data stream compatible with C++ you would need to do one of two things:

  1. Implement in C++ code that understands the output format produced by ObjectOutputStream -- i.e. re-implement in C++ what Java does in ObjectInputStream. This is NOT recommended.
  2. Write your data out from Java using a standard FileOutputStream, in a serialized format that you define, that then can be read by your C++ code. How you specify and implement this is up to you but can be very simple, depending on the complexity of your data.
Jim Garrison
  • 81,234
  • 19
  • 144
  • 183
  • 2
    Start by deciding what byte order ([endianness](https://en.wikipedia.org/wiki/Endianness)) you want to represent your binary data in. – rustyx Aug 30 '19 at 17:19
  • 1
    I'd suggest using [`DataOutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html), which will help write primitives in *big-endian* order. The class is specifically designed to write output "in a portable way". – Andreas Aug 30 '19 at 17:40
1

Yor write to file int (4 bytes?), in your file in hex must bu such data as 09 00 00 00. In your cpp code you read it to char array (you read bytes!), file.tellg(); return 4, and you read to char * memblock array {9, 0, 0, 0}. And after it you print it as chars cout << memblock[i] <<endl;. So you can print your out array as

for (i = 0; i < size / sizeof(int) / ; i++) {
   cout << ((int*)memblock)[i] <<endl;
}

or read it in int array

int* memblock;
...
memblock = new int[size / sizeof(int)];
...
file.read (memblock, (size / sizeof(int)) * sizeof(int));
1

Java code:

import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class Main
{

    public static void main( String[] args )
    {
        int x = 9;

        try
        {
            FileOutputStream fout = new FileOutputStream( "prueba.bin" );
            DataOutputStream salida = new DataOutputStream( fout );
            salida.writeInt( x );
            salida.close();
            System.out.println( "guardado" );
        }
        catch( Exception e )
        {
            System.out.println( e );
        }
    }
}

C++ Builder code:

unsigned char buffer[4];
ifstream file( "prueba.bin", ios::in | ios::binary );
if( file.is_open() )
{
    file.read( (char*)&buffer, sizeof( buffer ) );
    int num = buffer[ 0 ] | buffer[1] | buffer[ 2 ] | buffer[ 3 ];
    // another way to convert endianness:
    // int num = buffer[ 0 ] | ( buffer[1] << 8 ) | ( buffer[ 2 ] << 16 ) | ( buffer[ 3 ] << 24 );
}
Rufat
  • 196
  • 1
  • 2
  • 15