URGENT problem with compound files

Posted on 2000-03-27
Last Modified: 2013-11-20
I have written an application which used compound file storage, and I was having some peculiar things happening with the size of the files created by the program. So after much head scratching I decided to write a program with the minimum functionality which might exhibit the same problem, and see if it was something I was doing or something with MFC. I found that this minimum functionality program exhibited the same problem. SO I am wondering if anybody can figure what I need to do to fix it.

To create the minimum functionality program , use AppWizard to create an MFC app, (MDI or SDI, it doesn't matter), ensure that you make the application a container and enable compound files.

Overide the serialize method as follows

void CMyTestDoc::Serialize(CArchive& ar)
        if (ar.IsStoring())
                // TODO: add storing code here
                for (int i = 0; i < 100; i++)
                        ar << 0xAAAAAAAA;
                // TODO: add loading code here
                for (int i = 0; i < 100; i++)
                        DWORD temp;
                        ar >> temp;

        // Calling the base class COleDocument enables serialization
        //  of the container document's COleClientItem objects.

Run the application. Hit the save button on the toolbar. Save the file as XYZ.??? - or whatever you like. Quit the application. Check the size of the file you just saved. You will find that it is about 3.5k in size. You might want to make a copy of the file by cut and paste.

Now restart the application, load up the file you just saved, and then hit the save button again. Quit the application. If you now look at the file size - (you may need to press refresh if browsing the files using Explorer, becuase it doesn't seem to automatically refresh) - you will find that the file is 4.5k in size.

Examining the data file with the doc view shows that the new data is being appended to the file. When the file is read in the new data is being read, but the old data is still there, but not accesable.

Surely the data should have overwritten the old data, but it appears tht what it actually does is append it to the end of the file. Now when the file is so small this is not a problem. But I have files of 5mb or so, doubling up to 10mb.
Question by:mintcake
  • 3
  • 2

Expert Comment

ID: 2661051
It looks as though you are saving your files in transacted mode and you need to change that to direct mode. If you look in the MFC source you will see that all the streams are created with STGM_TRANSACTED but you need STGM_DIRECT.
I suspect it is a case of roll your own classes :( unless of course somebody else has already done them.

Expert Comment

ID: 2661490
You haven't shown how the CArchive is created.  It sounds like the document is being created in an append mode.

Serializing to a compound document is a reasonably complex process, and somewhere there may be an assumption lurking that you want to append a new stream to the document, rather than replace the document.  What I'd do is start tracing MFC code to see the way in which the file is opened.  It takes special effort to open a file for append, so this is not an accident; somewhere, there is a conscious decision in MFC to do this as an append operation.  Finding where that happens will tell you what you need to do to replace the document.  For example, there may be a CDocument state variable that controls append-vs-truncate.

Author Comment

ID: 2663531
I posted this problem on CodeGuru, and got the following response.

This happens because you are using the compound file and the way
MFC opens/commits storage, and of course the storage implementation :
MFC opens storage(COleDocumnet::m_lpRootStg) in transacted mode,
and commits it with the flag STGC_ONLYIFCURRENT.
This is the most safest way : if something happeng during save operation, old
data won't be lost.
The price is an extra disk space.
This probably not a problem for many (may be most) applications : these days
several megabytes is like several bytes 10 years ago.
If you really want to sacrifice robustness in favor of disk space, try to use the STGC_OVERWRITE in IStorage::Commit call.
You may want to overwrite SaveToStorage in your docuemnt class ( this is protected virtual function of COleDocument ) : copy this function from MFC source and change STGC_ONLYIFCURRENT to STGC_OVERWRITE.
Or ( it's not clean but should work ) do it in Serialize function
if ( ar.IsStoring )
//do your stuff
if ( m_lpRootStg )
// the second commit in ColeDocuemnt::SaveToStorage shouldn't do any harm
Hope this helps

Unfortunately this was posted anonymously, so I don't know who to thank, because after testing I found that this is the correct solution.
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.


Accepted Solution

ShaunWilde earned 200 total points
ID: 2663731
Glad you found it - at least I was close with the streams - you had better delete this question before someone answers it anyway

Author Comment

ID: 2663981
Not the correct answer but close.

Expert Comment

ID: 2664724
aww shucks - you shouldn't have :)

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
function returning CString in a regular win32 DLL 8 190
how to monitor remote shell execution on linux 9 104
dog bark java program 15 111
twoTwo  challenge 35 108
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question