Question

I'm into a "compatibility" issue between two versions of the same program, the first one written in Java, the second it's a port in C#.

My goal is to write some data to a file (for example, in Java), like a sequence of numbers, then to have the ability to read it in C#. Obviously, the operation should work in the reversed order.

For example, I want to write 3 numbers in sequence, represented with the following schema:

  • first number as one 'byte' (4 bit)
  • second number as one 'integer' (32 bit)
  • third number as one 'integer' (32 bit)

So, I can put on a new file the following sequence: 2 (as byte), 120 (as int32), 180 (as int32)

In Java, the writing procedure is more or less this one:

FileOutputStream outputStream;
byte[] byteToWrite;
// ... initialization....

// first byte
outputStream.write(first_byte);

// integers
byteToWrite = ByteBuffer.allocate(4).putInt(first_integer).array();
outputStream.write(byteToWrite);
byteToWrite = ByteBuffer.allocate(4).putInt(second_integer).array();
outputStream.write(byteToWrite);

outputStream.close();

While the reading part it's the following:

FileInputStream inputStream;
ByteBuffer byteToRead;
// ... initialization....

// first byte
first_byte = inputStream.read();

// integers
byteToRead = ByteBuffer.allocate(4);
inputStream.read(byteToRead.array());
first_integer = byteToRead.getInt();

byteToRead = ByteBuffer.allocate(4);
inputStream.read(byteToRead.array());
second_integer = byteToRead.getInt();

inputStream.close();

C# code is the following. Writing:

FileStream fs;
byte[] byteToWrite;
// ... initialization....

// first byte
byteToWrite = new byte[1];
byteToWrite[0] = first_byte;
fs.Write(byteToWrite, 0, byteToWrite.Length);

// integers
byteToWrite = BitConverter.GetBytes(first_integer);
fs.Write(byteToWrite, 0, byteToWrite.Length);
byteToWrite = BitConverter.GetBytes(second_integer);
fs.Write(byteToWrite, 0, byteToWrite.Length);

Reading:

FileStream fs;
byte[] byteToWrite;
// ... initialization....

// first byte
byte[] firstByteBuff = new byte[1];
fs.Read(firstByteBuff, 0, firstByteBuff.Length);
first_byte = firstByteBuff[0];

// integers
byteToRead = new byte[4 * 2];
fs.Read(byteToRead, 0, byteToRead.Length);
first_integer = BitConverter.ToInt32(byteToRead, 0);
second_integer = BitConverter.ToInt32(byteToRead, 4);

Please note that both the procedures works when the same Java/C# version of the program writes and reads the file. The problem is when I try to read a file written by the Java program from the C# version and viceversa. Readed integers are always "strange" numbers (like -1451020...).

There's surely a compatibility issue regarding the way Java stores and reads 32bit integer values (always signed, right?), in contrast to C#. How to handle this?

Was it helpful?

Solution

It's just an endian-ness issue. You can use my MiscUtil library to read big-endian data from .NET.

However, I would strongly advise a simpler approach to both your Java and your .NET:

Alternatively, consider just using text instead.

OTHER TIPS

I'd consider using a standard format like XML or JSON to store your data. Then you can use standard serializers in both Java and C# to read/write the file. This sort of approach lets you easily name the data fields, read it from many languages, be easily understandable if someone opens the file in a text editor, and more easily add data to be serialized.

E.g. you can read/write JSON with Gson in Java and Json.NET in C#. The class might look like this in C#:

public class MyData
{
    public byte FirstValue { get; set; }
    public int SecondValue { get; set; }
    public int ThirdValue { get; set; }
}

// serialize to string example
var myData = new MyData { FirstValue = 2, SecondValue = 5, ThirdValue = -1 };
string serialized = JsonConvert.SerializeObject(myData);

It would serialize to

{"FirstValue":2,"SecondValue":5,"ThirdValue":-1}

The Java would, similarly, be quite simple. You can find examples of how to read/write files in each library.

Or if an array would be a better model for your data:

string serialized = JsonConvert.SerializeObject(new[] { 2, 5, -1 }); // [2,5,-1]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top