0

Using the .NET Framework; is there a faster alternative to Convert.ToBase64String(byteArray)?

Update:

To give some further context, I am encoding file attachments for emails that differ by sender, so I'll be encoding quite a few (let's say 1000) >1MB files within a loop for this purpose.

A simplified example:

for(int i = 0; i < 1000; i++) {
    var file = System.IO.File.ReadAllBytes("c:\\temp\\clientfile" + i + ".pdf");
    System.IO.File.WriteAllText("c:\\emailsendtest\\test" + i + ".tmp", Convert.ToBase64String(file));
}
DanP
  • 6,310
  • 4
  • 40
  • 68

2 Answers2

5

Here is some data comparing the two methods (Convert... and Cryptography...). I ran 200 tests of writing out 1 million bytes to a new 1 MB file. It looks like the Convert.ToBase64 method is around seven times faster than the Cryptography method on average. The histogram of the test runs is below:

enter image description here

If anyone is interested in verifying my results - here is my test code:

private static void Test()
{

    Random myRand = new Random();

    List<TimeSpan> convert64Times = new List<TimeSpan>();
    List<TimeSpan> cryptoTimes = new List<TimeSpan>();
    Stopwatch theTimer = new Stopwatch();



    for (int i = 0; i < 200; i++)
    {

        byte[] randBytes = new byte[1000000];
        myRand.NextBytes(randBytes);

        string filePrefix = @"C:\Temp\file";


        // test encode with convert to base 64
        theTimer.Start();
        EncodeWithConvertToBase64(randBytes,filePrefix+i+"convert.txt");
        theTimer.Stop();
        convert64Times.Add(theTimer.Elapsed);
        theTimer.Reset();


        // test encode with crypto
        theTimer.Start();
        EncodeWithCryptoClass(randBytes,filePrefix+i+"crypto.txt");
        theTimer.Stop();
        cryptoTimes.Add(theTimer.Elapsed);
        theTimer.Reset();

    }
}



private static void EncodeWithConvertToBase64(byte[] inputBytes, string targetFile)
{
    string fileString = Convert.ToBase64String(inputBytes);

    using (StreamWriter output = new StreamWriter(targetFile))
    {
        output.Write(fileString);
        output.Close();
    }
}

private static void EncodeWithCryptoClass(byte[] inputBytes, string targetFile)
{

    FileStream outputFileStream =
        new FileStream(targetFile, FileMode.Create, FileAccess.Write);

    // Create a new ToBase64Transform object to convert to base 64.
    ToBase64Transform base64Transform = new ToBase64Transform();

    // Create a new byte array with the size of the output block size.
    byte[] outputBytes = new byte[base64Transform.OutputBlockSize];



    // Verify that multiple blocks can not be transformed.
    if (!base64Transform.CanTransformMultipleBlocks)
    {
        // Initializie the offset size.
        int inputOffset = 0;

        // Iterate through inputBytes transforming by blockSize.
        int inputBlockSize = base64Transform.InputBlockSize;

        while (inputBytes.Length - inputOffset > inputBlockSize)
        {
            base64Transform.TransformBlock(
                inputBytes,
                inputOffset,
                inputBytes.Length - inputOffset,
                outputBytes,
                0);

            inputOffset += base64Transform.InputBlockSize;
            outputFileStream.Write(
                outputBytes,
                0,
                base64Transform.OutputBlockSize);
        }

        // Transform the final block of data.
        outputBytes = base64Transform.TransformFinalBlock(
            inputBytes,
            inputOffset,
            inputBytes.Length - inputOffset);

        outputFileStream.Write(outputBytes, 0, outputBytes.Length);

    }

    // Determine if the current transform can be reused.
    if (!base64Transform.CanReuseTransform)
    {
        // Free up any used resources.
        base64Transform.Clear();
    }

    // Close file streams.

    outputFileStream.Close();
}
Jason Moore
  • 3,294
  • 15
  • 18
1

Assuming your file attachments are being read in as streams, it is recommended that you use the ToBase64Transform class in System.Security.Cryptography instead of the Convert class.

A full example can be found on that page which reads from an input file and writes back out an encoded file.

You should also take a look at JMarsch's example, found here.

Community
  • 1
  • 1
ahawker
  • 3,306
  • 24
  • 23
  • 1
    The question is; will this method actually be faster? I can see it using less memory, but that's not my bottleneck. – DanP Apr 26 '11 at 01:28