vector of fstream, does not work?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Someonekicked

    vector of fstream, does not work?

    In my program, I need to open multiple files, and I wont know till after the
    program execution how many of them (user will enter that value). So I am
    using a vector of fstream. I am using fstream since I will need to write and
    read from files, and I am using those files as binary files.

    I made a sample of what's going on (below). Without using vector, everything
    works fine, but with using vectors, something is going wrong somewhere!??

    I compiled the code with MS VC6++, and it compiled without errors, but still
    the piece of code with vectors wont give correct answer.
    with MSV .net 2003, compiling the code with vector will give me error,
    something about (no copy constructor available or copy constructor is
    declared 'explicit'), is that the problem?

    *********** First , without vector ********
    fstream inoutData;
    inoutData.open( "trial.txt" , ios::binary | ios::in | ios::out);
    if(!inoutData)
    {
    ofstream newfile;
    newfile.open("t rial.txt",ios:: binary);
    newfile.clear() ;
    newfile.close() ;
    inoutData.clear ();
    inoutData.open( "trial.txt" , ios::binary | ios::in | ios::out);
    }

    int p = 24;
    inoutData.clear ();
    inoutData.seekp (0);
    inoutData.write (reinterpret_ca st<const char *>(&p), sizeof(p));
    inoutData.seekg (0);
    int q;
    inoutData.read( reinterpret_cas t< char *>(&q), sizeof(q));
    cout << q << endl;


    *********** Second , with vector ********

    vector<fstream> inoutData(1);
    inoutData[0].open("trial.tx t", ios::binary | ios::in | ios::out);
    if(!inoutData[0])
    {
    ofstream newfile;
    newfile.open("t rial.txt",ios:: binary);
    newfile.clear() ;
    newfile.close() ;
    inoutData[0].clear();
    inoutData[0].open("trial.tx t", ios::binary | ios::in | ios::out);
    }

    int p = 24;
    inoutData[0].clear();
    inoutData[0].seekp(0);
    inoutData[0].write(reinterp ret_cast<const char *>(&p), sizeof(p));
    inoutData[0].seekg(0);
    int q;
    inoutData[0].read(reinterpr et_cast< char *>(&q), sizeof(q));
    cout << q << endl;


    --
    Quotes from The Weather Man:
    Robert Spritz: Do you know that the harder thing to do, and the right thing
    to do, are usually the same thing? "Easy" doesn't enter into grown-up
    life... to get anything of value, you have to sacrifice.


  • Jerry Coffin

    #2
    Re: vector of fstream, does not work?

    In article <UJedndOwS9MDNt zZRVn-qg@comcast.com> ,
    someonekicked@c omcast.net says...[color=blue]
    > In my program, I need to open multiple files, and I wont know till after the
    > program execution how many of them (user will enter that value). So I am
    > using a vector of fstream. I am using fstream since I will need to write and
    > read from files, and I am using those files as binary files.[/color]

    A vector of fstream isn't allowed. Anything you put into
    a vector must be assignable, and an fstream isn't -- the
    assignment operator is private in std::ios_base, and
    (unless I've missed something) none of its descendents
    makes it public again.

    You'll probably need to do something like an array of
    (possibly smart) pointers to fstreams instead.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.

    Comment

    • Tsubasa

      #3
      Re: vector of fstream, does not work?

      Jerry coffin, I find your error in your answer that is not
      std::ios_base but std::basic_ios, you know? 'cause the assignment
      operator is public in std::ios_base, and is private&not defined in
      std::basic_ios, although std::ios_base is the base of std::basic_ios,
      and std::basic_istr eam comes from std::basic_ios, std::fstream comes
      from std::basic_istr eam,
      I suppose that you might write error, don't you?

      Comment

      • Tsubasa

        #4
        Re: vector of fstream, does not work?

        and, OK, I ignore another mistake: anything you put into a vector must
        be assignable. It's not necessary, but copy constructor must be PUBLIC.

        Comment

        • Kai-Uwe Bux

          #5
          Re: vector of fstream, does not work?

          Tsubasa wrote:
          [color=blue]
          > Jerry coffin, I find your error in your answer that is not
          > std::ios_base but std::basic_ios, you know? 'cause the assignment
          > operator is public in std::ios_base, and is private&not defined in
          > std::basic_ios, although std::ios_base is the base of std::basic_ios,
          > and std::basic_istr eam comes from std::basic_ios, std::fstream comes
          > from std::basic_istr eam,
          > I suppose that you might write error, don't you?[/color]

          From the standard:

          27.4.2 Class ios_base

          namespace std {
          class ios_base {
          public:
          class failure;
          typedef T1 fmtflags;
          static const fmtflags boolalpha;
          ...
          [lots of stuff snipped]
          ...
          static bool sync_with_stdio (bool sync = true);
          protected:
          ios_base();
          private:
          // static int index; exposition only
          // long* iarray; exposition only
          // void** parray; exposition only
          private:
          ios_base(const ios_base&);
          ios_base& operator=(const ios_base&);
          };

          Note the private copy constructor and assignment operator, each of which by
          itself makes ios_base and classes derived therefrom unsuitable for use in
          std::vector.


          Best

          Kai-Uwe Bux


          Comment

          • Axter

            #6
            Re: vector of fstream, does not work?


            Someonekicked wrote:[color=blue]
            > In my program, I need to open multiple files, and I wont know till after the
            > program execution how many of them (user will enter that value). So I am
            > using a vector of fstream. I am using fstream since I will need to write and
            > read from files, and I am using those files as binary files.
            >
            > I made a sample of what's going on (below). Without using vector, everything
            > works fine, but with using vectors, something is going wrong somewhere!??
            >
            > I compiled the code with MS VC6++, and it compiled without errors, but still
            > the piece of code with vectors wont give correct answer.
            > with MSV .net 2003, compiling the code with vector will give me error,
            > something about (no copy constructor available or copy constructor is
            > declared 'explicit'), is that the problem?
            >
            > *********** First , without vector ********
            > fstream inoutData;
            > inoutData.open( "trial.txt" , ios::binary | ios::in | ios::out);
            > if(!inoutData)
            > {
            > ofstream newfile;
            > newfile.open("t rial.txt",ios:: binary);
            > newfile.clear() ;
            > newfile.close() ;
            > inoutData.clear ();
            > inoutData.open( "trial.txt" , ios::binary | ios::in | ios::out);
            > }
            >
            > int p = 24;
            > inoutData.clear ();
            > inoutData.seekp (0);
            > inoutData.write (reinterpret_ca st<const char *>(&p), sizeof(p));
            > inoutData.seekg (0);
            > int q;
            > inoutData.read( reinterpret_cas t< char *>(&q), sizeof(q));
            > cout << q << endl;
            >
            >
            > *********** Second , with vector ********
            >
            > vector<fstream> inoutData(1);
            > inoutData[0].open("trial.tx t", ios::binary | ios::in | ios::out);
            > if(!inoutData[0])
            > {
            > ofstream newfile;
            > newfile.open("t rial.txt",ios:: binary);
            > newfile.clear() ;
            > newfile.close() ;
            > inoutData[0].clear();
            > inoutData[0].open("trial.tx t", ios::binary | ios::in | ios::out);
            > }
            >
            > int p = 24;
            > inoutData[0].clear();
            > inoutData[0].seekp(0);
            > inoutData[0].write(reinterp ret_cast<const char *>(&p), sizeof(p));
            > inoutData[0].seekg(0);
            > int q;
            > inoutData[0].read(reinterpr et_cast< char *>(&q), sizeof(q));
            > cout << q << endl;
            >[/color]

            IAW C++ standard, iostream and derived class fstream are not assignable
            or copiable, which means you can't use it as a concrete object in your
            vector.
            However, you could create a vector of pointer to fstream.
            I would recommend using a smart pointer like boost::shared_p tr
            See following link of list of smart pointers:


            And see following link for example usage of smart pointers:


            Comment

            • Jerry Coffin

              #7
              Re: vector of fstream, does not work?

              In article <1145181037.707 901.163820
              @i40g2000cwc.go oglegroups.com> , chanmaosheng@gm ail.com
              says...[color=blue]
              > Jerry coffin, I find your error in your answer that is not
              > std::ios_base but std::basic_ios, you know? 'cause the assignment
              > operator is public in std::ios_base, and is private&not defined in
              > std::basic_ios, although std::ios_base is the base of std::basic_ios,
              > and std::basic_istr eam comes from std::basic_ios, std::fstream comes
              > from std::basic_istr eam,
              > I suppose that you might write error, don't you?[/color]

              I was pretty sure ios_base declared them private, but
              maybe my memory has failed me.

              It's more or less beside the point which base class
              causes it though. Creating a vector of X requires that X
              be copyable and assignable. Streams are neither copyable
              nor assignable, so you can't create vectors of streams.

              --
              Later,
              Jerry.

              The universe is a figment of its own imagination.

              Comment

              • Howard Hinnant

                #8
                Re: vector of fstream, does not work?

                In article <UJedndOwS9MDNt zZRVn-qg@comcast.com> ,
                "Someonekic ked" <someonekicked@ comcast.net> wrote:
                [color=blue]
                > In my program, I need to open multiple files, and I wont know till after the
                > program execution how many of them (user will enter that value). So I am
                > using a vector of fstream. I am using fstream since I will need to write and
                > read from files, and I am using those files as binary files.[/color]

                In addition to the good answers you've already received, I'd like to
                add: The committee is seriously considering changes to the C++ language
                and standard library which allow your "with vector" example to work
                exactly as you coded it.

                Reference:



                -Howard

                Comment

                • Tom

                  #9
                  Re: vector of fstream, does not work?

                  In my opinion, the element type used for vector should be a value-like
                  type. And the fstream, manages a file handler, cannot be copy and
                  assign.

                  Comment

                  • Howard Hinnant

                    #10
                    Re: vector of fstream, does not work?

                    In article <1145331383.368 727.253240@i39g 2000cwa.googleg roups.com>,
                    "Tom" <yeyesho@gmail. com> wrote:
                    [color=blue]
                    > In my opinion, the element type used for vector should be a value-like
                    > type. And the fstream, manages a file handler, cannot be copy and
                    > assign.[/color]

                    No worries.

                    vector::value_t ype will continue to be value-like. And fstream will
                    continue to be non-copyable and non-assignable. Move semantics
                    introduces a powerful new way of looking at things that compliments your
                    existing views, and allows things to be more efficient, not less.

                    Consider:

                    std::fstream
                    open_the_file_m y_way(const char* filename)
                    {
                    std::fstream result ...
                    return result;
                    }

                    ....

                    void test ()
                    {
                    std::fstream my_file = open_the_file_m y_way("the file");
                    ...
                    }

                    There is no logic error above. Every time the fstream changes
                    locations, the old location is about to be destroyed. The underlying
                    file handle can be passed from fstream to fstream, and no one is the
                    wiser. You get what today seems like copy behavior, but really is move
                    behavior.

                    At the same time, you will still be prohibited from copying or assigning
                    fstreams:

                    void test ()
                    {
                    std::fstream my_file = open_the_file_m y_way("the file"); // ok
                    ...
                    std::fstream another_file = my_file; // won't compile
                    }

                    Here if the copy succeeded you would have two streams running around
                    pointing to the same file. I think we're all agreed that would be a bad
                    thing. This will continue to be enforced at compile time.
                    [color=blue]
                    > *********** Second , with vector ********
                    >
                    > vector<fstream> inoutData(1);
                    > inoutData[0].open("trial.tx t", ios::binary | ios::in | ios::out);
                    > if(!inoutData[0])
                    > {
                    > ofstream newfile;
                    > newfile.open("t rial.txt",ios:: binary);
                    > newfile.clear() ;
                    > newfile.close() ;
                    > inoutData[0].clear();
                    > inoutData[0].open("trial.tx t", ios::binary | ios::in | ios::out);
                    > }
                    >
                    > int p = 24;
                    > inoutData[0].clear();
                    > inoutData[0].seekp(0);
                    > inoutData[0].write(reinterp ret_cast<const char *>(&p), sizeof(p));
                    > inoutData[0].seekg(0);
                    > int q;
                    > inoutData[0].read(reinterpr et_cast< char *>(&q), sizeof(q));
                    > cout << q << endl;[/color]

                    In the OP's code, the fstream is never copied, even while it is inside
                    the vector. If the OP attempts an operation with the vector<fstream>
                    that would *visibly* copy an fstream, the compiler will reject it. E.g.

                    vector<fstream> inoutData(1); // ok
                    fstream f = inoutData[0]; // compile time error
                    inoutData.push_ back(fstream("a nother file")); // ok

                    In the latest example, no one has a reference to that temporary being
                    put into the vector. There's no danger of two fstreams pointing to the
                    same file.

                    fstream f;
                    inoutData.push_ back(f); // compile time error

                    If this compiled, then both f and inoutData.back( ) would point to the
                    same file (bad!).

                    -Howard

                    Comment

                    Working...