Reading and writing binary strings in C++ and C#

Started by
3 comments, last by Nypyren 13 years, 5 months ago
Hello, all the text parsing for levels that my game use became too complicated to manage. So I did some research on saving the level as a binary file, it was pretty easy until I came to the strings used for the textures. The game is in C++ and the level editor is in C#, how can I write a string in C# and then read it in C++ again? I thought about writing the size of the string and then the chars that were in it, but I couldn't figure out how :(.
Advertisement
I just did this a few months ago for a project at College:

What I did was have a SaveFileDialog which allowed the user to select the file to save to, which would then pass the filename into a FileStream which was then passed into BinaryWriter in which case to write a string it's just:

myBinaryWriter.Write(myString);


Now to read it in C++ is pretty easy, first just have a char to temporarily store the data from your ifstream into that char which will be number of characters in the string, then you loop from 0 - numofchars-1 reading in each char and putting it into a std::string.

// Open the filestd::ifstream myFile("File.file",std::ios::binary|std::ios::in);char tempBuffer;int numOfChars;std::string myString;// Read the number of characters in my stringmyFile->read(&tempBuffer,(sizeoftempBuffer));numOfChars = (int) tempBuffer;for(int i = 0;i<numOfChars; i++){myFile->read((char*) (&tempBuffer), sizeof(tempBuffer));myString->append(1,tempBuffer);}

Engineering Manager at Deloitte Australia

Excuse my ignorance, but what exactly is a binary string?

Stephen M. Webb
Professional Free Software Developer

Quote:Original post by Bregma
Excuse my ignorance, but what exactly is a binary string?


I assume he means some arbitrary-length sequence of bytes, to be interpreted as bytes rather than characters (via whatever encoding).
When C# writes out a string into a BinaryWriter, it first writes what it calls a 7 bit encoded length.

That means:

length of 0 to 127 is stored in one byte, with the high bit of that byte == 0.

length of 128 to 16383 is stored in two bytes, with the low 7 bits in the low 7 bits of the first byte, the high bit of the first byte == 1, and the remaining bits go in the second byte.

Even longer strings just keep adding extra bytes until there's no more bits in the length to write.


It's pretty easy to write a decoder for that format, but why bother? The format is only used because they wanted it to be as space-efficient as possible.

It would be much easier to just write out a fixed-size integer if you don't mind always using 4 bytes for a length prefix. Or, if you know your strings will always be shorter than 256, or always shorter than 65536, you could use 1 or 2 bytes. This requires using C# that looks like this:

void WriteBinaryString(BinaryWriter bw, string s){  bw.Write(s.Length); // optional: cast to a ushort or byte.  bw.Write(s.ToCharArray());  // Note: the null terminator is not written.}


You'll have to tack on a terminator yourself before or after reading the chars into your array.

Depending on what character encoding your C++ side uses (typically ASCII or Unicode), you may need to use Encoding.whicheveroneyouwant.GetBytes() instead of string.ToCharArray:

byte[] bytes = Encoding.ASCII.GetBytes(inputString);binaryWriter.Write(bytes.Length); // optionally cast it.binaryWriter.Write(bytes);

This topic is closed to new replies.

Advertisement