2011-04-26 71 views
0

使用.NET Framework;有沒有更快的替代Convert.ToBase64String(byteArray)Convert.ToBase64String的更快選擇?

更新:

爲了讓一些進一步的情況下,我的編碼文件附件爲按發件人不同的郵件,所以我會編碼相當多的(比如說1000)>在一個循環中1MB文件以此目的。

一個簡單的例子:

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)); 
} 
+8

你能解釋這是怎麼慢? – 2011-04-26 00:19:13

+3

,你需要多快? – R0MANARMY 2011-04-26 00:22:28

+0

你在做什麼Convert.ToBase64String太慢?很頻繁地調用它或使用大量數據?根據你在做什麼,在.NET中重新實現它可能會更快,或者調用本地C實現。 – Skrymsli 2011-04-26 00:22:52

回答

1

假設您的文件附件被讀入作爲流,建議您使用System.Security.Cryptography的ToBase64Transform類,而不是轉換類。

在該頁面上可以找到完整的示例,該頁面從輸入文件讀取並寫回編碼文件。

你也應該看看JMarsch的例子,找到here

+0

問題是,這種方法會更快嗎?我可以用更少的內存來看它,但那不是我的瓶頸。 – DanP 2011-04-26 01:28:57

4

以下是比較兩種方法(Convert ...和Cryptography ...)的一些數據。我跑了200個測試,寫出100萬字節到一個新的1 MB文件。它看起來像Convert.ToBase64方法的平均速度比密碼學方法快7倍左右。測試運行的直方圖低於:

enter image description here

如果有人有興趣驗證我的結果 - 這是我的測試代碼:

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(); 
}