Ahmad Siavashi Ahmad Siavashi - 1 month ago 8
C++ Question

Reopening a closed file stream

Consider the following code,

auto fin = ifstream("address", ios::binary);
if(fin.is_open())
fin.close()
for(auto i = 0; i < N; ++i){
fin.open()
// ....
// read (next) b bytes...
// ....
fin.close()
// Some delay
}


The code above can't be implemented in the C++ I know, but I'd like to know if it is possible to do so?

Here are my requirements:


  • When reopening the file, there would be no need to pass the parameters (path and mode) again.

  • When reopening the stream, it continues from the point in the stream that it was when got closed.



Clarification




  • The files I work with are big in size and in a point of time other threads from third party libraries may decide to (re)move them. An open stream will prevent such actions.

  • Continuously reading a big file will slow down the system.


Answer

The need

Indeed, a file can't be deleted by another process as long as a stream keeps it open.

I suppose you have already asked yourself these questions, but fo the recors I have to suggest you to think about it:

  • Can't the file be read into (virtual) memory and discarded when no longer needed ?
  • Can't the file processing be pipelined asynchronously, to read it at once and process it without unnecessary delays ?
  • What to do if the file can no longer be opened because it was deleted by the other process ? What to do if the location can't be found, because the file was modified (e.g. shortened) ?
  • If you would have the perfect solution to your issue, what would be the effect if the other process would try to delete the file when it is open (only for a short time, but nevertheless open and blocking the deletion) ?

The solution

Unfortunately, you can't achieve the desired behavior with standard streams. You could emulate it by keeping track of the filename and of the position (and more generally of the state):

   auto mypos = ifs.tellg();  // saves position.  
                              // Should flag be saved as well ? and what about gcount ?
   ifs.close();  

   ...

   if (! ifs.is_open()) {
       ifs.open(myfilename, myflags);  // open again !  
       if (! ifs) { 
           // ouch ! file disapeared ==> process error 
       }
       ifs.seekg(mypos);              // restore position 
       if (! ifs) { 
           // ouch ! position no longer reachable  ==> process error 
       }
   }

Of course, you wouldn't like to repeat this code ever and ever. And it would not be so nice having all the sudden a lot of global variables to keep track of the stream's state. But you could very easily encapsulate it in a wrapper class that would take care of saving and restoring the stream's state using existing standard operations.