6

I have the following code:

   ofstream mOutFile.open(logPath, ios_base::app);
   string lBuilder;

   lBuilder.append("========================================================\n");
   lBuilder.append("Date: ");
   lBuilder.append(asctime(timeinfo));
   lBuilder.append("\n");
   lBuilder.append("Log Message:\n");
   lBuilder.append(toLog);
   lBuilder.append("\n");
   lBuilder.append("========================================================\n\n");

   int lSize = lBuilder.size();
   char* lBuffer = new char[lSize];
   int index = 0;
   for each (char c in lBuilder)
      lBuffer[index++] = c;

   mOutFile.write(lBuffer, lSize);
   mOutFile.flush();

Unfortunately, until I close the app (I assume that closing the ofstream would work as well) the output does not get written to the text file. I know I could probably close and reopen the stream and everything will "just work" but that seems like a silly and incorrect solution. What am I doing wrong here?

I have also tried the following variations based on other questions I have found here, but these solutions did not work:

mOutputFile << flush;
mOutputFile << endl;

Thanks in advance for any assistance on this.

edit Everything in this code is working visual c++, it builds and works fine except the file is not written to until the stream is closed, even if I force a flush. Also, I switched from using the << operator to the char * and .write () to see if anything behaved differently.

codewario
  • 19,553
  • 20
  • 90
  • 159
  • 2
    Why kind of syntax is : `for each (char c in lBuilder)`. That's not valid C++. – Charles Salvia Mar 09 '12 at 21:15
  • Is there a reason you're not using << to write strings to the file? – ebutusov Mar 09 '12 at 21:17
  • The `for each` seems like a C#ism. Also, try closing the file handle after you flush it and see if that helps. – Mr. Llama Mar 09 '12 at 21:17
  • It might be that there's buffering below the C++ level by the operating system. Maybe this question is helpful for you: http://stackoverflow.com/questions/4473064/force-ofstream-file-flush-on-windows – celtschk Mar 09 '12 at 21:26
  • 1
    @CharlesSalvia: AFAIK the `for each` syntax is C++/CLI. – celtschk Mar 09 '12 at 21:29
  • 2
    @CharlesSalvia: `for each` is a Microsoft extension, and `lBuffer` is a `char*`, not a string. – Benjamin Lindley Mar 09 '12 at 21:30
  • 1
    @ruakh: This is not necessarily c++-cli. The extension is available in native C++ in Visual Studio, without the /clr option. And since the question is about features that are available in standard c++, I think the C++ tag is appropriate. – Benjamin Lindley Mar 09 '12 at 21:39
  • 1
    @BasedAsFunk: Copying the string to a dynamic array is error-prone and completely unnecessary. You could have written to the file directly with the string like this: `mOutFile.write(lBuilder.c_str(),lBuilder.size());` – Benjamin Lindley Mar 09 '12 at 21:56
  • @celtschk: Thanks for that link, but none of the solutions fixed the issue. I ended up just closing and reopening the stream and that seems to work, though that solution makes me cringe. – codewario Mar 12 '12 at 13:36
  • @ebutusov: No, my original code was much better, but I became frustrated and tried different things thinking maybe there might be something I was doing wrong to force the flush. – codewario Mar 12 '12 at 13:37

3 Answers3

9
std::ofstream file(logPath, ios_base::app);

file << "========================================================\n"
     << "Date: " << asctime(timeinfo)
     << "\nLog Message:\n" << toLog
     << "\n========================================================\n\n"
     << std::flush; 
     //if you want to force it write to the file it will also flush when the the file object is destroyed
//file will close itself

This is not only easier to read but it will probably also be faster than your method + it is a more standard appraoch

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
111111
  • 15,686
  • 6
  • 47
  • 62
2

I ended up just "making it work" by closing and reopening the stream after the write operation.

mOutputFile << "all of my text" << endl;
mOutputFile.close();
mOutputFile.open(mLogPath);

EDIT After trying out forcing the flush on a few other systems, it looks like something just isn't performing correctly on my development machine. Not good news but at least the above solution seems to work when programmatically flushing the ofstream fails. I am not sure of the implications of the above code though, so if anyone wants to chime in if there are implications of closing and reopening the stream like this.

codewario
  • 19,553
  • 20
  • 90
  • 159
  • looks like this is the case, the flush works fine on other systems – codewario Mar 12 '12 at 16:19
  • is the file being held open by another process or anything like that, (in a *NIX environment you can use lsof). – 111111 Mar 12 '12 at 16:40
  • I really doubt it, since I have the file being created by this program and the write completes once the stream is closed. This PC has always had a couple of quirks though, just strange something as simple as flushing a file stream fails on it. – codewario Mar 13 '12 at 10:57
  • You're not alone, I either get nothing written to the file, or I have to close/reopen. – Akumaburn May 26 '17 at 14:40
  • Same issue am also facing – Gilson PJ Jan 23 '18 at 02:58
0

You can perform the following steps to validate some assumptions:

1.) After flush(), the changes to the file should be visible to your application. Open the file as std::fstream instead of std::ofstream. After flushing, reset the file pointer to the beginning and read the contents of the file. Your newly written record should be there. If not, you probably have a memory corruption somewhere in your code.

2.) Open the same file in an std::ifstream after your call to flush(). Then read the contents of the file. Your newly written record should be there. If not, then there's probably another process interfering with your file.

If both works, then you may want to read up on "file locking" and "inter-process syncronization". The OS can (theoretically) take as much time as it wants to make file changes visible to other processes.

ManuelAtWork
  • 2,198
  • 29
  • 34