2

In C,C++ if you write an integer in binary way(e.g. fwrite(&someInt,sizeof(int),1,fp)) say to file, you have tons of issues to consider if you want to read that integer from different machine - e.g., endianness issues, integer size may vary on other computer, float representation may vary on different computer, negative integers have different representation, etc. So directly reading and writing in binary mode may not work across different computers.

In this example below using Binary reader (from MSDN), do above issues also apply?

using System;
using System.IO;

class ConsoleApplication
{
    const string fileName = "AppSettings.dat";

    static void Main()
    {
        WriteDefaultValues();
        DisplayValues();
    }

    public static void WriteDefaultValues()
    {
        using (BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Create)))
        {
            writer.Write(1.250F);
            writer.Write(@"c:\Temp");
            writer.Write(10);
            writer.Write(true);
        }
    }

    public static void DisplayValues()
    {
        float aspectRatio;
        string tempDirectory;
        int autoSaveTime;
        bool showStatusBar;

        if (File.Exists(fileName))
        {
            using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
            {
                aspectRatio = reader.ReadSingle();
                tempDirectory = reader.ReadString();
                autoSaveTime = reader.ReadInt32();
                showStatusBar = reader.ReadBoolean();
            }

            Console.WriteLine("Aspect ratio set to: " + aspectRatio);
            Console.WriteLine("Temp directory is: " + tempDirectory);
            Console.WriteLine("Auto save time set to: " + autoSaveTime);
            Console.WriteLine("Show status bar: " + showStatusBar);
        }
    }
}

What about BinaryFormatter class?

  • Are you assuming the same executable is used on all machines? If you have to recompile on each machine then you have the same issue since you defined an 'int' for autoSaveTime. Now if you used Int32 instead then it would be ok. – jdweng May 24 '15 at 10:53
  • @jdweng: I am not sure what you mean but say yes - I assume same executable. But I may be referring also to sending one integer over network from one computer to another one, etc. ps I thought in C# int32 is alias for int .. so why the difference? –  May 24 '15 at 10:55
  • If you are using the same executable, then the setting for integer size is built into the executable. So it is portable. Yes an integer is always 32 on XP to present, but not Win95 or possibly 64 in the future. – jdweng May 24 '15 at 12:07

1 Answers1

2
  • The endianess of the BinaryWriter is fixed. It is always little endian.
  • The integer size is always the same for each data type: byte/sbyte 1B short/ushort 2B int/uint 4B long/ulong 8B
  • Floats and Doubles follow the IEEE Standart
  • Reading and writing with the BinaryReader/BinaryWriter will bring the same result. From C# to Java you would need to flip all incoming bytes because Java is using BigEndian
  • The BinaryFormatter is meant to serializes or deserializes objects on the same PC. It should not be used when transferring data from one PC to another.

If you are working with two C# Applications simply use the BinaryReader/BinaryWriter, they are portable. If the other end is not programmed with C# you will most likely need to use (or write your own) class to handle such issues.

a-ctor
  • 3,109
  • 20
  • 38
  • 1
    BinaryFormatter is not a good system for serializing data across a wire, it was designed with IPC within the same machine in mind. It is extremely sensitive to version changes to any assemblies in the object graph of the serialized object and I have heard stories where two computers could not communicate because of differing patch levels of windows updates relating to .NET. – Scott Chamberlain May 24 '15 at 11:05
  • @ScottChamberlain: that is my question if BinaryReader, BinaryWriter, BinaryFormatter, can be used to serialize data in portable way –  May 24 '15 at 11:08
  • @user44333 reader and writer, yes. Formatter, no. Also be careful of `BitConverter` that class can also convert things to `byte[]`'s but `BitConverter` is sensitive to the endianess of the machine it is running on (BineryReader and Writer always use little endian no matter the computer architecture). – Scott Chamberlain May 24 '15 at 11:10
  • @ScottChamberlain: Is text serialization like XML guaranteed to be portable? So binary reader and writer I can use for serializing data structures .. –  May 24 '15 at 11:31
  • Yes it is, but there is a choice of encoding for text which is set in the constructor. Be sure both sides are set to the same value. – Scott Chamberlain May 24 '15 at 11:45
  • @ScottChamberlain: Yes I know about encoding. Why I would choose XML serialization over using BinaryReader and Writer? (ps I was particularly interested about floats too but seems encoding them both in XML and BinaryWriter is portable) –  May 24 '15 at 11:50
  • Odd to pick on BinaryFormatter, BinaryWriter is a *lot* worse. The reader just produces complete garbage when the writer changes, the odds for an exception are not very good. – Hans Passant May 24 '15 at 12:24
  • BinaryFormatter is intended to be usable as a durable, portable format. It is the bassis for WCF NetTCP binding and ASP.NET session state (sharable across machines). It's just that the rules to make it work are complicated and difficult to test for. – usr May 24 '15 at 12:37
  • @HansPassant: Can you please elaborate? What do you mean if the writer changes? –  May 24 '15 at 12:55
  • @usr: do I get the feel that there is no consistent answer on this question so far? different opinions? –  May 24 '15 at 12:56
  • @user44333 well, this is not an opinion... This answer is wrong regarding BinaryFormatter but right regarding the rest. If you want advice: Use a higher-level format such as protobuf, XML, JSON, ... These issues simply do not show up then. – usr May 24 '15 at 12:59
  • @usr: You mean this is not right: "The BinaryFormatter is meant to serializes or deserializes objects on the same PC. It should not be used when transferring data from one PC to another." ?? Ok, I see about XML. Was interested if I could also use binary reader/writer for that -seems I can? thanks for the advice; somewhere I noticed saying encoding float to string and then reading back might not always work(and since XML is text file ... ?but you say this is not issue) –  May 24 '15 at 13:08
  • I don't know about XML and floats. Floats have a round-trip string format, though. That's all I know. – usr May 24 '15 at 13:35