Sign in to follow this  
Rubenknex

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

Recommended Posts

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 :(.

Share this post


Link to post
Share on other sites
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 file
std::ifstream myFile("File.file",std::ios::binary|std::ios::in);

char tempBuffer;
int numOfChars;
std::string myString;

// Read the number of characters in my string
myFile->read(&tempBuffer,(sizeoftempBuffer));
numOfChars = (int) tempBuffer;

for(int i = 0;i<numOfChars; i++)
{
myFile->read((char*) (&tempBuffer), sizeof(tempBuffer));
myString->append(1,tempBuffer);
}


Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this