Thread: Closing a stream

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    271

    Closing a stream

    How would you "close" a stream that might be instantiated as a stream that cannot be closed?

    Specifically, there are programs that default to stdout if you don't specify an output file but can have other forms of output. The code would probably be something like:

    Code:
    ostream* os;
    
    if (argc[X] != '-')
       os = &cout;
    else
       os = new ofstream("out");
    Then before the program terminates, you'd (want to) have
    Code:
    os->close();
    Which obviously will throw an error since ostream doesn't have a "close" method. One work around could be
    Code:
    if(some boolean flag indicating that you have a file stream has been set)
       os->close();
    But what I would like to know is whether there is a way of instantiating a "stream" in a way as to make it possible to "close" it in runtime with only methods internal to the stream class.

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Code:
    if(os != &cout)
    {
    }
    maybe?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    I hadn't tried it out, but the compiler just won't allow
    Code:
    os->close()
    whether it's in a conditional or not.

    In a situation where you have just one file output file, it will be closed if the program terminates (I'm guessing there might be messy situations where this isn't true and you'll have trouble deleting the file because a program didn't close the file properly), but what if you didn't use some argument from the command line as a file name but as an output header?
    Code:
    if(argv[X][0] != '-')
        os = &cout;
    else
        os = new ofstream(output_header + number);
    ....
    while(forever)
    {
        os = new ofstream(output_header + different_number);
        os->close(); ////Won't compile
    }
    In this situation, that would be big problem because you'd have leaking file handles. And I don't think there'd be any viable workaround to it.

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I think you have a bit of a problem there. You shouldn't close streams explicitly at all. Instead you should let the destructor handle that. However, you have placed yourself in a situation where you don't know whether the stream pointer has been allocated with new, so you can't simply call delete on it.

    However, I think there are ways to redirect streams properly. If I'm not mistaken that would involve calls to rdbuf (and no dynamic allocation, perhaps).

    For my own purposes, I just use what the OS provides for redirecting stdout to file (while printing output that needs to go to console in any case to std::cerr). For example on Windows:
    C:\>myprog > output.txt
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Did you know that a stream would close itself when it is destructed? Proper application of scope should be about all that you need to manage streams like cout or another file. So, in other words, its okay to tie cout to a reference and not worry about when it is closed. There is a problem with this approach if you attempt to reopen a file in the program though.

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Quote Originally Posted by anon View Post
    You shouldn't close streams explicitly at all. Instead you should let the destructor handle that.
    Huh? I thought file output streams had to be closed. So you're saying instead of
    Code:
    os->close();
    this
    Code:
    delete os;
    would not only deallocate memory but close the stream as well (if it's a file stream)? That makes things easier and clear then. You'd just have to keep track of whether "os" is "cout" or not.

  7. #7
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Quote Originally Posted by citizen View Post
    There is a problem with this approach if you attempt to reopen a file in the program though.
    I'll keep that in mind. Thanks.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by cunnus88 View Post
    Huh? I thought file output streams had to be closed. So you're saying instead of
    Code:
    os->close();
    this
    Code:
    delete os;
    would not only deallocate memory but close the stream as well (if it's a file stream)? That makes things easier and clear then. You'd just have to keep track of whether "os" is "cout" or not.
    Yeah, since the stream closes when the destructor is run (that's what happens when an object goes out of scope), that will work.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If you want to redirect cout for a long time (if you are outputting in only one place, you could wrap it in a function and pass it the correct stream), it might look something like that.

    (It may not be quite right since I don't use this in practice.)

    Code:
    #include <iostream>
    #include <fstream>
    #include <limits>
    
    using namespace std;
    
    int main()
    {
        char answer;
        cout << "Print to file [f] or to console [c]? ";
        cin >> answer;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    
        {
            //initialize to cout buffer to be able to restore
            std::streambuf* buf = cout.rdbuf();
    
            ofstream fout;
            if (answer == 'f') {
                fout.open("testing.txt");
                cout.rdbuf(fout.rdbuf()); //redirect cout to file
            }
    
            cout << "Testing redirection.\n"; //print somewhere
    
            //restore console output
            cout.rdbuf(buf);
        } //fout gets closed here - if it was opened in the first place
    
        cout << "We are done now.";
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Discard wrong data from stream
    By mesmer in forum C Programming
    Replies: 7
    Last Post: 11-16-2008, 02:30 AM
  2. Interpreter.c
    By moussa in forum C Programming
    Replies: 4
    Last Post: 05-28-2008, 05:59 PM
  3. Problem with empty stream
    By sshahar1 in forum C Programming
    Replies: 8
    Last Post: 09-03-2007, 05:00 PM
  4. Closing the input stream after a certain time
    By happyhippo404 in forum C++ Programming
    Replies: 3
    Last Post: 10-08-2005, 12:23 AM
  5. Help! About text stream and binary stream
    By Antigloss in forum C Programming
    Replies: 1
    Last Post: 09-01-2005, 08:40 AM