Writing EOF into an output stream

Is there anyway to insert an EOF into an output stream to truncate the underlying file?

I have code that reads a five-line text file in with ifstream, closes it, opens a stream for output with ofstream on the same file, writes out the first four lines read in, and closes the output stream.  I want the file to be terminated after the fourth line I write back out, but the EOF for the file hasn't moved, so that displaying the file with notepad still shows all five lines.  How can I truncate this file at the end of my write?

Thanks,
Steve
stevaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Nass89Commented:
Hi,
Use seekg() and position the stream pointe,r where you want. Then close it.

Good Luck!

0
AndyAinscowFreelance programmer / ConsultantCommented:
ofstream( const char* szName, int nMode = ios::out, int nProt = filebuf::openprot );

ofstream( filedesc fd );

ofstream( filedesc fd, char* pch, int nLength );

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values:

ios::app   The function performs a seek to the end of file. When new bytes are written to the file, they are always appended to the end, even if the position is moved with the ostream::seekp function.


ios::ate   The function performs a seek to the end of file. When the first new byte is written to the file, it is appended to the end, but when subsequent bytes are written, they are written to the current position.


ios::in   If this mode is specified, then the original file (if it exists) will not be truncated.


ios::out   The file is opened for output (implied for all ofstream objects).


ios::trunc   If the file already exists, its contents are discarded. This mode is implied if ios::out is specified and ios::ate, ios::app, and ios:in are not specified.


According to help you should be trashing the contents of the file with the ofstream UNLESS you specif y another flag that keeps the contents.  You should post some code.  Also try sending some other text to ofstream to see if the file is actually having anything written to it at all.
0
stevaAuthor Commented:
Andy, I think you may have hit on the problem when you said - "UNLESS you specify another flag that keeps its contents."

When I open the output stream on the file I write
 
    ofstream x_out(fileName, ios::in | ios::out);

After doing some experimenting, I see that  it's the ios::in flag that keeps the contents, i.e., keeps the file pointer at the end of the original file even though the put pointer is short of the end when I close the file. If I just use ios::out, or default (no flags) the EOF get's written after the last byte that I write to the file, and I truncate the file as I want to do.

But the answer isn't as simple as removing ios::in.  After much pain, I discovered last month that this is required to open this particular file for output because the file has "hidden" and "system" attributes. (It's actually boot.ini.)

I wrestled with this issue last month here at Experts Exchange, and after resolving that the ios::in | ios::out was needed to open a system/hidden file to an output stream in Windows, the best advice offered was that "hidden and system attributes were OS-specific and standard C++ does not provide tools to work with them."  No one knew why including the ios::in flag did the trick and opened the file for output.

So now I'm stuck.  I can't open the file for output without the ios::in flag but with the ios::in flag I can't shorten the file, as I need to do.

Does anyone see a way around this?

Steve

0
AndyAinscowFreelance programmer / ConsultantCommented:
CFile::GetStatus
BOOL GetStatus( CFileStatus& rStatus ) const;

static BOOL PASCAL GetStatus( LPCTSTR lpszFileName, CFileStatus& rStatus );

Return Value

TRUE if the status information for the specified file is successfully obtained; otherwise, FALSE.

Parameters

rStatus

A reference to a user-supplied CFileStatus structure that will receive the status information. The CFileStatus structure has the following fields:

CTime m_ctime   The date and time the file was created.


CTime m_mtime   The date and time the file was last modified.


CTime m_atime   The date and time the file was last accessed for reading.


LONG m_size   The logical size of the file in bytes, as reported by the DIR command.


BYTE m_attribute   The attribute byte of the file.


char m_szFullName[_MAX_PATH]   The absolute filename in the Windows character set.
lpszFileName

A string in the Windows character set that is the path to the desired file. The path can be relative or absolute, but cannot contain a network name.

Remarks

The virtual version of GetStatus retrieves the status of the open file associated with this CFile object. It does not insert a value into the m_szFullName structure member.

The static version gets the status of the named file and copies the filename to m_szFullName. This function obtains the file status from the directory entry without actually opening the file. It is useful for testing the existence and access rights of a file.

The m_attribute is the file attribute. The Microsoft Foundation classes provide an enum type attribute so that you can specify attributes symbolically:

enum Attribute {
   normal =    0x00,
   readOnly =  0x01,
   hidden =    0x02,
   system =    0x04,
   volume =    0x08,
   directory = 0x10,
   archive =   0x20
   };


What you need to do is modify the attributes of the file, then open for writing (AND reset back to original afterwards).  If I remember correctly (from something I did years ago) for system files you would need to remove the system and the hidden attributes in different steps.  The order I can't remember.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
stevaAuthor Commented:
Yes!  I had the same thought when I woke up this morning - and this does work. I didn't have a problem changing the permissions in any sequence.  The code that works is simply...

       fileAttributes = GetFileAttributes(boot_file);
       SetFileAttributes(boot_file, FILE_ATTRIBUTE_NORMAL);
       ofstream boot_out(boot_file);

                ... modify file

       boot_out.close();
       SetFileAttributes(boot_file, fileAttributes);

Thanks for the help!   I released the point to you.

Steve
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.