Followup question from "Temporarily redirect output of Print[ ] to a second file

I'm implementing the first answer to my earlier question about redirecting the output of Print[ ]. Opening a file with OpenWrite[] and assigning the stream to $Output seems to work satisfactorily. However, Close[] gives the error message shown below, and doesn't close the file. Does anyone know what's wrong? (Print statements and other code goes between opening the output stream and attempting to close it) - 1 Answer Your problem is with not reassigning $Output back to stdout. You could do it by writing your code like so:

fname = FileNameJoin[{HomeDirectory[], "Desktop", "test.txt"}];
Module[{out = $Output},$Output = OpenWrite[fname, FormatType -> OutputForm];
Write[$Output, "The quick brown fox ..."]; Print[$Output];
Close[$Output];$Output = out]


The file written out by this code looks like this:

The quick brown fox ...
OutputStream[/Users/oldmg/Desktop/test.txt, 126]

The file is properly closed and no error messages ensue. However, I don't think that's good practice. I much prefer this approach which makes reassignment unnecessary:

Block[{$Output = OpenWrite[fname, FormatType -> OutputForm]}, Write[$Output, "The quick brown fox ..."];
Print[$Output]; Close[$Output]]


Edit

As rcollyer points out in a comment, it is a good idea have some error handling; in particular, the file should be closed even if an abort should occur between the time the file is opened and the time it is closed.

Block[{$Output, rtn}, rtn = OpenWrite[fname, FormatType -> OutputForm]; If[rtn ===$Failed,
$Failed, AbortProtect[$Output = rtn;
Write[$Output, "The quick brown fox ..."]; Print[$Output];
Close[\$Output]]]]

-
Something like this code, maybe? –  rcollyer Aug 13 '13 at 1:29
@rcollyer. Yes, but I wasn't aware of that post. I neglected to follow the link to it given above. It looks like the OP didn't thoroughly understand the advice given there, so still needs a push in the right direction. –  m_goldberg Aug 13 '13 at 2:50
Likely that is exactly what happened. My only issue with your code is there is no error handling. If an Abort is issued, the stream is not closed. This question has a few strategies for handling that. –  rcollyer Aug 13 '13 at 3:00
Yes, it would be better wrap the file I/O with AbortProtect. I'll make an update that does that. –  m_goldberg Aug 13 '13 at 3:07
To toot my own horn, I like BlockStream, but there is some evidence that InternalWithLocalSettings` handles most cases, and I tend to use it almost exclusively, now. Definitely something to keep in ones tool chest. –  rcollyer Aug 13 '13 at 3:18