7

In some code that does a lot of file i/o using std::ofstream, I'm caching the stream for efficiency. However, sometimes I need to change the openmode of the file (e.g. append vs truncate). Here is some similar mock code:

class Logger {
public:
    void write(const std::string& str, std::ios_base::openmode mode) {
        if (!myStream.is_open) myStream.open(path.c_str(), mode);
        /* Want: if (myStream.mode != mode) {
                     myStream.close();
                     myStream.open(path.c_str(), mode);
                 }
        */
        myStream << str;
     }
private:
    std::ofstream myStream;
    std::string path = "/foo/bar/baz";
}

Does anyone know if:

  • There is a way to change the openmode of the ofstream?
  • If not, is there a way to find out what the current openmode of an ofstream is so I can close and reopen it only when necessary?
Ari
  • 1,102
  • 9
  • 17
  • You might want to read about [these](http://en.cppreference.com/w/cpp/io/basic_ofstream) state functions, that allow you set or return state of the flags..... – Recker Nov 21 '12 at 16:53
  • I am just curious why would you want to change it? When does such a condition apply? – Bartek Banachewicz Nov 21 '12 at 17:03
  • 2
    @noleptr I looked at those, but they don't let you change the openmode of the file. You can only get/set `goodbit`, `badbit`, `failbit`, `eofbit`. @BartekBanachewicz I'm redoing the implementation of part of a library. I'm not sure in what scenario you actually need this either, but I need to maintain the same behavior as before. Previously this was done with platform-specific system calls that do let you query the state of the file. – Ari Nov 21 '12 at 17:32
  • You might manually have to set the stream pointer depending on the flags you want to set – dchhetri Nov 21 '12 at 17:40
  • @user814628 could you elaborate a bit more please? – Ari Nov 21 '12 at 18:20
  • @BartekBanachewicz - I ran into this problem parsing 3d model files. The "ply" file format is implicitly ASCII until it reaches the line "end_header", then the format switches to whatever was specified by the "format" directive in said header. To 'switch' modes, I use tellg, close, reopen, and seekg to the saved position. Hopefully that's no more of a crapshoot than I/O is normally... – John P Feb 25 '16 at 21:43

1 Answers1

4

@Ari Since the default implementation doesn't allow what you want todo, you might have to encapsulate ofstream and provide the additional get/set open mode functionality in which your new object would simulate the desired behavior.

Maybe something like so

class FileOutput{
  private:
    ostream& streamOut;
    std::ios_base::openmode currentOpemMode;
  public:
    FileOutput(ostream& out, std::ios_base::openmode mode)
     : streamOut(out), currentOpemMode(mode){}

    void setOpenMode(const std::ios_base::openmode newOpenMode){
          if(newOpenMode != currentOpemMode){
              currentOpemMode = newOpenMode;
              updateUsedMode();
          }
    }
  private:
    void updateUsedMode(){
          if(currentOpemMode == ios_base::app){  /* use seekg/tellg to move pointer to end of file */}
          else if(currentOpenMode == binary){ /* close stream and reopen in binary mode*/}
         //...and so on
};
dchhetri
  • 6,926
  • 4
  • 43
  • 56