Do you need to "close" a FileOutputStream when using TemporaryFile?

Documentation for overwriteTargetFileWithTemporary() says:

Before calling this, make sure:
that you’ve actually written to the temporary file
that you’ve closed any open streams that you were using to write to it
and that you don’t have any streams open to the target file, which would prevent it being overwritten

So, I was trying to find any examples of closing the outputStream, but I can’t find any.

I’ve seen this kind of thing a lot (pseudo code):

    // create the file specifier
    File file = File::getCurrentWorkingDirectory().getChildFile("someFileName");

    // create a tempFile to write to
    TemporaryFile tempFile(file);
    
    // create a stream to write to it
    FileOutputStream output(tempFile.getFile());

    if (output.openedOk())
    {
        // .... write some data to it

        // when done, swap the temp file
        bool success = tempFile.overwriteTargetFileWithTemporary();
        if (!success)
        {
            // flag some error
        }
    }

How do you “close any open stream you were using to write to it?”

I believe it is closed when the stream object is destroyed (aka goes out of scope).

Well, yes that is true. However, the quoted instructions in the documentation of overwriteTargetFileWithTemporary say Before calling this, close it. In the example code I posted, which is what I have found in several places, no one is actively closing it, and it will go out of scope after overwriteTargetFileWithTemporary is called. So I guess the documentation is incorrect?

Is it wrong, or does it fail under certain conditions? maybe it behaves differently on different OS’s? shrug

One of the great things about JUCE is that you can easily look at the source. A quick exploration of overwriteTargetFileWithTemporary doesn’t show that the file is getting closed. So, I believe the docs are correct. Why would you choose to not close it? a simple set of curly braces can give you scope.

I saw it fail on windows with JUCE 5 when it is used like the example in the docs.
The same code worked fine on mac.

I had no time yet to see if this is different now in JUCE 6 (the project in question was client’s code that couldn’t be updated).

1 Like

Are you saying it failed when used like the above example at the top?

The reason I am asking is I cannot find an example of FileOutputStream being closed in some way before overwriteTargetFileWithTemporary is called. Not with scoping or any other way.

I guess you could do something like:

    // create the file specifier
    File file = File::getCurrentWorkingDirectory().getChildFile("someFileName");

    // create a tempFile to write to
    TemporaryFile tempFile(file);

    {    // scoping
    
        // create a stream to write to it
        FileOutputStream output(tempFile.getFile());

        if (!output.openedOk())
        {
            // abort
            return;
        }

        // else continue
        // .... write some data to it

    } // end scoping, which closes the FileOutputStream

    // when done, swap the temp file
    bool success = tempFile.overwriteTargetFileWithTemporary();
    if (!success)
    {
        // flag some error
    }

At the moment, it seems to work fine (on Mac) without any scoping or “closing” of the FileOutputStream. It’s just my first time working with these classes, and when I read about overwriteTargetFileWithTemporary() it struck me as odd that no one seems to be closing the FileOutputStream

1 Like

Yes I can confirm that the first code you posted will fail on Windows (at least from my experience even with the latest Juce). You need to scope the stream like you did in your last post.

1 Like

Thank you for that confirmation! It would be great if JUCE provide an example of how to use the TemporaryFile class during data saving in the examples somewhere.

Have a look at the jucer_CommandLine.cpp file in the Projucer project. The zipModule function there uses TemporaryFile, and it shows some of the error checking you’d want to use with it and FileOutputStream.

1 Like