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?”
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 afteroverwriteTargetFileWithTemporary 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.
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…
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.
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.