1

I have a C++ program that is writing to a file on Windows 7. When I call f.flush() the NTFS file does not get bigger. Is there any way to force the file to get flushed?

vy32
  • 28,461
  • 37
  • 122
  • 246
  • Are you sure there is pending output? Also, fsync (or [`_commit`]()) is your friend (http://archives.postgresql.org/pgsql-hackers-win32/2003-11/msg00082.php) – sehe Nov 12 '11 at 21:30
  • Oh, yes, I'm positive there is output. It's not pending --- it's been sent. But NTFS buffers. – vy32 Nov 12 '11 at 22:05
  • It is a heavy CRT implementation detail. For the MSVC CRT it is done by passing 'c' (= commit) to the fopen() *mode* argument. Look through the source of the one you use. – Hans Passant Nov 12 '11 at 22:59

2 Answers2

2

You can look here:
How do I get the file HANDLE from the fopen FILE structure?
the code looks like this:

 FlushFileBuffers((HANDLE) _fileno(_file));

do not forget call fflush(file), before call FlusFileBuffers.

For std::fstream and gnu stl, I checked it on my linux box, have no windows at home, but should work with mingw, may be need some modifications:

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <fstream>
#include <ext/stdio_filebuf.h>


int main(int argc, char *argv[])
{
    assert(argc == 2);
    std::ifstream f(argv[1]);
    assert(!!f);
/*
    //cin, cout etc
    __gnu_cxx::stdio_filebuf<char> *stdio_buf = dynamic_cast<__gnu_cxx::stdio_filebuf<char> *>(f.rdbuf());
    if (stdio_buf != 0) {
        printf("your fd is %d\n", stdio_buf->fd());
        return EXIT_SUCCESS;
    }
*/
    std::basic_filebuf<char> *file_buf = dynamic_cast<std::basic_filebuf<char> *>(f.rdbuf());
    if (file_buf != 0) {
        struct to_get_protected_member : public std::basic_filebuf<char> {
            int fd() { return _M_file.fd(); }
        };
        printf("your fd is %d\n", static_cast<to_get_protected_member *>(file_buf)->fd());
    }
    printf("what is going on?\n");
    return EXIT_FAILURE;
}
Community
  • 1
  • 1
fghj
  • 8,898
  • 4
  • 28
  • 56
  • But that is a C `FILE*` object, not a C++ `iostream` object. – vy32 Nov 12 '11 at 21:01
  • This is more hard, in library that come with VS10, you can construct std::fstream object from FILE, on some other libraries, I saw std::fstream::fd method, to file descriptor from std::fstream. What compiler do you use? – fghj Nov 12 '11 at 21:13
  • I'm using mingw as a cross-compiler from Fedora Core. So I'm using GNU STL. – vy32 Nov 12 '11 at 22:06
  • I did not find a `f.fd()` method. – vy32 Nov 12 '11 at 22:06
  • Update my answer, to include code that I was used some time before to get file handle. – fghj Nov 12 '11 at 22:47
  • @user1034749 This is much better than my `#define protected public` trick!! – nodakai Oct 05 '12 at 07:06
  • Btw `dynamic_cast` wasn't necessary with g++ 4.6.3 / Ubuntu 12.04 LTS – nodakai Oct 05 '12 at 07:23
0

flush only flushes the internal buffers kept by the standard library code.

To flush the OS's buffers, you'd need/want to call FlushFileBuffers (after calling f.flush()).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • That's great. However, `FlushFileBuffers` requires the hFile handle. How do I get that? http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439(v=vs.85).aspx – vy32 Nov 12 '11 at 20:47
  • fsync() doesn't do the trick; I need to call FlushFileBuffers; I just need to find the handle. – vy32 Nov 12 '11 at 21:36