Jump to content
  • Advertisement
Sign in to follow this  
MatsK

How do I write values correctly to an ofstream?

This topic is 2660 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi!
I tried writing to an ofstream.

First I just did

ofstream Archive(Replace(m_ArchivePath, ".dat", ".tmp").c_str());


to create it and

Archive << "FAR!byAZ"; //Signature
Archive << )3; //Version
Archive << 0x00; //ManifestOffset


to write to it. This seemed to assume that all values were written as text.
So I tried

ofstream Archive(Replace(m_ArchivePath, ".dat", ".tmp").c_str(), ios::binary);


to create it and

Archive << "FAR!byAZ"; //Signature
Archive << (unsigned int)3; //Version
Archive << (unsigned int)0x00; //ManifestOffset



to write to it.

But my C# program still can't read from it! Leading me to believe that the values are still encoded as text. So what am I doing wrong?

Edit: The header (which is just 8 ASCII characters) is read fine, but the numbers are not read correctly.

Share this post


Link to post
Share on other sites
Advertisement
What is the code for reading the values? Have you looked at your dat file in a hex editor (or a text editor )?

Share this post


Link to post
Share on other sites
Yeah I've looked at it in a text editor and quite frankly it looks the same to me regardless of how I write it.

Share this post


Link to post
Share on other sites
The code for reading the two first parts of the header is as follows:

private ArchiveType DetermineArchiveType(string Path)
{
BinaryReader Reader = new BinaryReader(File.Open(Path, FileMode.Open));

string Header = Encoding.ASCII.GetString(Reader.ReadBytes(8));

if (Header == "FAR!byAZ")
{
uint Version = Reader.ReadUInt32();
MessageBox.Show("Version: " + Version.ToString());

if (Version == 3)
{
Reader.Close();
return ArchiveType.FAR3;
}

Reader.Close();
return ArchiveType.FAR;
}

Reader.Close();
return ArchiveType.DBPF;
}



Version is always printed as 808529971

Share this post


Link to post
Share on other sites
Have you counted the number of bytes that should be written and compared that to the size of the file? Is there a terminating null after the header that you're not accounting for?

Share this post


Link to post
Share on other sites
May I suggest using binary serialization? It's quite simple once you learn it, and offers many options for reading and writing data via a stream. Heres a tutorial I found helpfull.

http://www.codeproject.com/KB/cs/objserial.aspx

Share this post


Link to post
Share on other sites
Are you suggesting I use serialization to read the file with C#?
I'm confused. I am writing the data with C++.

Share this post


Link to post
Share on other sites
The ostream operator << and >> only write out in text mode. If you want to dump specific bytes to a file you need to use the read() and write() interface to the fstream to perform binary io.

As for any confusion on the std::ios::binary flag you pass when opening the stream, all that does is change how the text-mode << and >> convert specific symbols like \r\n in the file.

Share this post


Link to post
Share on other sites
Hm.
After alot of debugging, I've discovered that my program crashes on what seems to be the second of these statements:

Archive << "FAR!byAZ";
Archive.write(reinterpret_cast<const char*>(Version), 4);
Archive.write(reinterpret_cast<const char*>(ManifestOffset), 4);
Archive.flush();



Here is how I create the archive:

unsigned int Version = 3;
unsigned int ManifestOffset = 0x00;

ofstream Archive(Replace(m_ArchivePath, ".dat", ".tmp").c_str(), ios::binary);


I tried removing ios::binary, but it didn't change anything. I'm not exactly sure what the error is, but confusingly enough, Visual Studio opens 'memcpy.asm' when the program crashes.

Share this post


Link to post
Share on other sites

Hm.
After alot of debugging, I've discovered that my program crashes on what seems to be the second of these statements:

Archive << "FAR!byAZ";
Archive.write(reinterpret_cast<const char*>(Version), 4);
Archive.write(reinterpret_cast<const char*>(ManifestOffset), 4);
Archive.flush();



That makes sense. Read up on what reinterpret_cast does. Hint: it does not convert data from one type to another.

Your code is telling the compiler to treat the integer value Version as a memory address and read 4 bytes from that location. Since 0x00000003 isn't a valid virtual address, the process crashes.

My guess is you intended to write either the sequence of bytes "00 00 00 03" or "03 00 00 00". In either case, the correct, portable way to do that is one byte at a time with bitwise operations.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!