Interesting problem: serializing in with MFC CArchive, reading out using C# BinaryReader

R

RP2001

I've serialized in various variables of various types (mainly CString,
int, double) into an instantiated MFC CArchive class and saved it as a
binary file.

I am able to open the binary file and read out the individual
variables fine with an MFC application. However I cannot read the
binary file correctly with a C#.NET application, where I'm using the
BinaryReader Class. Doing some debugging I noticed that the problem
occured at this C# line of code:

my_variable_of_type_CString =
instantiated_CSharp_binaryreader.ReadString();

When this line of code execute, the binary reads out the ENTIRE
remainder of the file. So I thought is this one of those hairy, good
old string termination issues, but I've checked the byte representing
the string termination and it's there.

Another strange thing that I noticed is that the first ASCII character
that is suppose to be there as part of the string being read out, is
not being interpreted.

Two other things I want to point out that is specific to my situation
and it is that the string being read out from the binary file has two
consecutive carriage returns and line feeds ("\r\n\r\n"). Also I'm
trying to read out two string consecutively. Could these two aspects
attribute to the problem?

Example, when I use the Studio.NET debugger to see what is contained
in my_variable_of_type_CString, I get something like this:

my_variable_of_type_CString = "ew York City\vNext String to be read
out\0\0\0 . . . (garbage until the end of file"

Any help will be GREATLY appreciated. Thanks in advance.

-RP
 
A

Airjoe

Hello,

I am planning to write a C# application that needs to read binary files
created with MFC serialization.

Have you made any progress on solving your issues? If so any information
would be appreciated

Thanks,

J
 
L

Luis Barreira

A few months ago I had the same problem. I solved it by looking into the MFC
source code and converting the needed code to C#:

public class MFCStringReader : System.IO.BinaryReader
{
public MFCStringReader(Stream s) : base(s)
{
}

public MFCStringReader(Stream s, Encoding e) : base(s, e)
{
}

public string ReadCString()
{
string str = "";
int nConvert = 1; // if we get ANSI, convert

UInt32 nNewLen = ReadStringLength();
if (nNewLen == unchecked((UInt32)(-1)))
{
nConvert = 1 - nConvert;
nNewLen = ReadStringLength();
if (nNewLen == unchecked((UInt32)(-1)))
return str;
}

// set length of string to new length
UInt32 nByteLen = nNewLen;
nByteLen += (UInt32)(nByteLen * (1 - nConvert)); // bytes to read

// read in the characters
if (nNewLen != 0)
{
// read new data
byte[] byteBuf = ReadBytes((int)nByteLen);

// convert the data if as necessary
StringBuilder sb = new StringBuilder();
if (nConvert != 0)
{
for (int i = 0; i < nNewLen; i++)
sb.Append((char)byteBuf);
}
else
{
for (int i = 0; i < nNewLen; i++)
sb.Append((char)(byteBuf[i*2] + byteBuf[i*2+1] * 256));
}

str = sb.ToString();
}

return str;
}

private UInt32 ReadStringLength()
{
UInt32 nNewLen;

// attempt BYTE length first
byte bLen = ReadByte();

if (bLen < 0xff)
return bLen;

// attempt WORD length
UInt16 wLen = ReadUInt16();
if (wLen == 0xfffe)
{
// UNICODE string prefix (length will follow)
return unchecked((UInt32)(-1));
}
else if (wLen == 0xffff)
{
// read DWORD of length
nNewLen = ReadUInt32();
return nNewLen;
}
else
return wLen;
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top