Save MemoryBlock to Disk - This works but is there a better way?

I couldn’t find much at all about how to save an existing MemoryBlock to Disk, whilst also giving the user a choice of Directory and Filename. After about 2 days I’ve finally hit on a FileChooser and FileOutputStream combination that works, but it must be hacky as I’m not great with C++

Would anyone care to comment?

void  SaveToDiskAudioProcessorEditor::saveFile(juce::MemoryBlock mb_to_save)
{
    auto path = juce::File::getSpecialLocation(juce::File::userHomeDirectory);

    myFile = std::make_unique<juce::FileChooser>("Export As", path, "*.syx;", true);

    auto folderChooserFlags = juce::FileBrowserComponent::saveMode | juce::FileBrowserComponent::canSelectFiles;

    if (mb_to_save.getSize() != 0)
    {
    myFile->launchAsync(folderChooserFlags, [this, mb_to_save](const juce::FileChooser& chooser)
        {
            auto outFile = chooser.getResult();
            auto newDefDir = outFile.getParentDirectory().getFullPathName();
            outFile.create();

            juce::FileOutputStream fos(outFile);
            fos.write(mb_to_save.getData(), mb_to_save.getSize());
            fos.flush();
        });
    }
}

Looks pretty good I’ve had a go at cleaning it up slightly but be warned the below code is untested. There is at least one subtle behaviour change in my version. If the memory block is empty I leave the function before recreating the FileChooser, maybe you intentionally did it after so it acts as a way to cancel the current fileChooser?

void SaveToDiskAudioProcessorEditor::saveFile (const juce::MemoryBlock& newFileContents)
{
    // Are you sure you don't want to carry out the work if the contents of the memory block are empty?
    if (newFileContents.isEmpty())
        return;

    const auto path = juce::File::getSpecialLocation (juce::File::userHomeDirectory);
    fileChooser = std::make_unique<juce::FileChooser> ("Export As", path, "*.syx;");

     // You might want to warn users if they are overwriting an existing file?
    const auto folderChooserFlags = juce::FileBrowserComponent::saveMode 
                                  | juce::FileBrowserComponent::canSelectFiles
                                  | juce::FileBrowserComponent::warnAboutOverwriting; 

    fileChooser->launchAsync (folderChooserFlags, [newFileContents](auto chooser)
    {
        // A FileOutputStream should already create the file if it doesn't exist 
        FileOutputStream output (chooser.getResult());

        // It's wise to check it worked, for example the result of the chooser might be invalid if the user cancelled the dialog
        if (output.openedOk())
        {
            // If the file already exists you probably want to clear it's contents before writing to it
            output.setPosition (0);
            output.truncate();
            output.write (newFileContents.getData(), newFileContents.getSize());
        }
    });
}

Thanks for the tips Anthony, much appreciated!

I’ve tweaked it to this:

void  SaveToDiskAudioProcessorEditor::saveMemoryBlockToDisk(juce::MemoryBlock& mb_to_save)
{
    if (mb_to_save.getSize() != 0)
    {
    auto path = juce::File::getSpecialLocation(juce::File::userHomeDirectory);
    fileChooser = std::make_unique<juce::FileChooser>("Export As", path, "*.syx;", true);
    auto folderChooserFlags = juce::FileBrowserComponent::saveMode | juce::FileBrowserComponent::canSelectFiles | juce::FileBrowserComponent::warnAboutOverwriting;
   
        fileChooser->launchAsync(folderChooserFlags, [mb_to_save](const juce::FileChooser& chooser)
            {
                auto outFile = chooser.getResult();
                juce::FileOutputStream fos(outFile);

                if (fos.openedOk())
                {
                    fos.setPosition(0);
                    fos.truncate();
                    fos.write(mb_to_save.getData(), mb_to_save.getSize());
                }
            });
    }
    else
    {
        showBubbleMessage("No Data!");
    }
}

If the MemoryBlock hasn’t been filled yet, it doesn’t do anything except throw up a Bubble Message that there’s No Data!

Any ideas on how to remember the last Directory, at the moment it’s just defaulting to the userHomeDirectory which is fine, but remembering and going back to the last folder saved to would be nicer!