Base64 Encoding a Large File

I’m currently struggling to find the proper way to convert a large file (~50-100mb) to a Base64 string. I currently have:

    // Get the file from the temp directory
    const File largeFile (File::getSpecialLocation (File::tempDirectory)
                     .getChildFile ("AudioRecording.wav"));
    // send input stream to Base64::toBase64
    String b64 = Base64::toBase64(largeFile.createInputStream(), largeFile.getSize());

However this is writing each chunk of the stream into b64 resulting in a lot of repeated data What would be the proper way to handle this flow?

Thanks!
Tomek

try this:

const File largeFile (File::getSpecialLocation (File::tempDirectory)
                 .getChildFile ("AudioRecording.wav"));
MemoryBlock mb;
ScopedPointer<FileInputStream> fis = largeFile.createInputStream();
fis->readIntoMemoryBlock( mb );
auto s = Base64::toBase64( mb.getData(), mb.getSize() );
    or
auto s = mb.toBase64Encoding(); //read documentation
3 Likes

Yep, that’s exactly what I was looking for. Thanks!

Yeah, if you ever see (const void*, size_t size) as the parameter, you gotta convert whatever data you’re dealing with into a MemoryBlock first and then mb.getData(), mb.getSize() as the args. And use those stream methods that write to and read from a MemoryBlock

Yea the thought with trying to use the InputStream from the file was to conserve on memory. With the memory block, I’m copying the file contents into a memory buffer, then when I convert it to Base64 and put it into a String, then i’m pretty much making another copy of that and storing that in memory also. Finally, I stuff it into a URL object (where it possibly gets copied again?), so a 50mb file might take up to 150mb of memory?

Maybe I should call mb.reset() right after I convert it to a Base64 string.

If you use the scope pointer and create them on the stack you don’t have to worry about any of that because when the function exits, it’ll deconstruct them automatically

1 Like