1

Okay, so I've got a game map creater programmed in Java which writes the map out to file using ObjectOutputStream.writeInt()

Now I'm converting the game engine to C# XNA and I'm trying to load the map. I'm getting numerical errors though, so I'm wondering if anyone knows what I'm doing wrong?

Java writes as int 32 Big Endian I believe (I could be wrong though).

Here is the code I'm using to read the height and width of the map in C#.

Edit: br is BinaryReader.

width = (int)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(br.ReadBytes(sizeof(int)), 0));
height = (int)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(br.ReadBytes(sizeof(int)), 0));

Can anyone please tell me what I'm doing wrong? Or how to read the bytes from ObjectOutputStream.writeInt() properly in C#?

Edit: 2nd try failed. here is the current code:

public byte[] ReadBigEndianBytes(int count, BinaryReader br)
        {
            byte[] bytes = new byte[count];
            for (int i = count - 1; i >= 0; i--)
                bytes[i] = br.ReadByte();

            return bytes;
        }

        public void loadFile(int level)
        {
            FileStream fs = new FileStream("map" + level + ".lv", FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs, System.Text.Encoding.BigEndianUnicode);

            width =  BitConverter.ToInt32(ReadBigEndianBytes(4, br), 0);
            height = BitConverter.ToInt32(ReadBigEndianBytes(4, br), 0);

            tile = new int[width, height];

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    tile[x, y] = BitConverter.ToInt32(ReadBigEndianBytes(4, br), 0);
                }
            }

        }
    }
4
  • Personally, I would be reading this with shift operators, rather than assuming the machine's endianness. Commented Sep 12, 2011 at 20:46
  • The BinaryReader has ReadXXX methods, for example BinaryReader.ReadInt32 (msdn.microsoft.com/en-us/library/…), but note that ReadUint32 reads in little-endian Commented Sep 12, 2011 at 20:47
  • Here is an example Big-Endian BinaryReader wrapper that has minimal functionality: stackoverflow.com/questions/123918/… or Jon Skeet's MiscUtils EndianBinaryReader (yoda.arachsys.com/csharp/miscutil) Commented Sep 12, 2011 at 20:53
  • Tried using the SO one, and it didn't work, but the other one's src is so big I dunno where to begin. Commented Sep 12, 2011 at 21:08

3 Answers 3

2
ObjectOutputStream.writeInt()

Don't use that. Use DataOutputStream.writeInt(). It does the same thing, in network byte order, but it doesn't add the Serialziation header that ObjectOutputStream adds, so you won't have to skip it at the .NET end.

Sign up to request clarification or add additional context in comments.

Comments

1

Absolutely correct:

Java writes as int 32 Big Endian I believe (I could be wrong though).

Remember, though: a .Net Int32 is Little-Endian ;)

[Edit] SOLUTION:

1) Here is Java code that writes 10 integers (Java int's are 32-bit, Big-endian))


    import java.io.*;

    public class WriteBinary {

      public static void main (String[] args) {
        int[] data = {
          1, 2, 3, 4, 5, 6, 7, 8, 9, 10
        };

        String fname = "myfile.bin";
        try
        {
          System.out.println("Opening " + fname + "...");      
          FileOutputStream fos = 
            new FileOutputStream(fname);
          int ibyte;
          for (int i = 0; i < data.length; i++) {
            ibyte = ((data[i] >>> 24) & 0xff); fos.write(ibyte);
            ibyte = ((data[i] >>> 16) & 0xff); fos.write(ibyte);
            ibyte = ((data[i] >>> 8) & 0xff); fos.write(ibyte);
            ibyte = (data[i] & 0xff); fos.write(ibyte);
          }
          fos.close();
          System.out.println("File write complete.");      
        }
        catch (IOException e) {
          System.out.println ("I/O error: " + e.getMessage());
        }
      }
    }

2) Here is the C# code that reads it. You'll notice the "using System.Net", in order to get .Net's equivalent of "ntohl()":



using System;
using System.IO;
using System.Net;

namespace ReadBinary
{
    class Program
    {
        static void Main(string[] args)
        {
            string fname = "myfile.bin";
            try
            {
                Console.WriteLine("Opening " + fname + "...");
                BinaryReader br =
                  new BinaryReader(
                        File.Open(fname, FileMode.Open));
                for (int i = 0; i < (int)(br.BaseStream.Length / 4); i++)
                {
                    int j =
                        System.Net.IPAddress.NetworkToHostOrder (br.ReadInt32());
                    Console.WriteLine("array[" + i + "]=" + j + "...");
                }
                br.Close();
                Console.WriteLine("Read complete.");
            }
            catch (IOException ex)
            {
                Console.WriteLine("I/O error" + ex.Message);
            }
        }
    }
}

3 Comments

Actually a .NET int isn't really defined as either-endian. MS .NET does happen to be little endian pretty much everywhere, but that isn't guaranteed on mono.
Can you give an example of output C# side in what doesn't work in this example? The above code looks dead on for writing the stream. Also, how "garbled" is the input? Are you using ObjectOutputStream (Java side)? My guess here is that you have additional information at the top and bottom of your streams, but without that information I can't really say. ObjectOutputStream is dangerous in this situation. It really should be a standard OutputStream.
@CyanPrime - Please take a look at the code example I added last night.
0

I think a proper way is to use IPAddress.NetworkToHostOrder(Int32) method.

public void loadFile(int level)
    {
        ...

        width =  IPAddress.NetworkToHostOrder(br.ReadInt32());
        height = IPAddress.NetworkToHostOrder(br.ReadInt32());

        ...

    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.