简体   繁体   中英

CFile::osNoBuffer flag causes exception when writing to file

(WINAPI create file - WINAPI write file) Flag used in winapi (FILE_FLAG_NO_BUFFERING) works fine, when I use winapi functions to write the file.

(WINAPI create file - CFile - write file) In this situation the error also had occured, but it was because of absent file name in CFile object, that was created from the file handle received from winapi CreateFile-function.

(CFile create file - Cfile - write file ) When I use this flag (CFile::osNoBuffer), the exception appears when I try to write something to the file, talking me that some unrecognized error occured.

what may be wrong?

char chArr [] = "1234567890";
CFile file;
file.Open("c:\\mfc.txt",CFile::modeCreate| CFile::modeNoTruncate| CFile::modeWrite | CFile::osNoBuffer | CFile::osWriteThrough);
file.Write(chArr,sizeof(chArr)); // exception 
file.Flush(); 
file.Close();

See this discussion of file buffering on MSDN.

Opening the file with the flag CFile::osNoBuffer , or passing the flag FILE_FLAG_NO_BUFFERING to CreateFile , is quite a special way of writing to the file. It requires that all buffers you use to write to the file are aligned to a sector boundary in memory, and also that you only write an integer multiple of the sector size. Unless you've taken special steps to align the buffer you're passing (which you haven't here), and also written at least eg 512 bytes, it's unlikely that it will work unless the device silently ignores your flag. I think you possibly didn't notice that WriteFile returned an error code instead of throwing an exception.

I would ask: why are you specifying this flag at all? Its use is quite specialized, and if you're just doing normal everyday file I/O, like writing a text file, then you should not specify this flag. It probably slows down your program, and makes it more complicated as well. I also recommend that you remove CFile::osWriteThrough .

Just so you know: the use of FILE_FLAG_NO_BUFFERING is almost exclusively for things writing a massive amount of data that must go directly to disk, such as real-time data logging or video recording applications. FILE_FLAG_WRITE_THROUGH is used for things like database log files that must be flushed after every write for transactional correctness. Disabling these caches and buffers in other cases generally slows down your program.

Here's another discussion of someone with the same problem (though they were using .NET, not C++).

Edit: Thanks for mentioning the size requirement Daryl.

From the MSDN file buffering discussion Doug mentioned in his answer..

  • File access sizes, including the optional file offset in the OVERLAPPED structure, if specified, must be for a number of bytes that is an integer multiple of the volume sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1,024, 1,536, or 2,048 bytes, but not of 335, 981, or 7,171 bytes.

  • File access buffer addresses for read and write operations should be sector-aligned, which means aligned on addresses in memory that are integer multiples of the volume sector size. Depending on the disk, this requirement may not be enforced.

On my system, changing...

char chArr[] = "1234567890";

to

char chArr[512] = "1234567890";

...gets rid of the exception but with the obvious problem that I'm now writing a bunch of uninitialized junk bytes to the file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM