[英]BitConverter.ToString() vs Convert.ToBase64String()
[英]Base64 - CryptoStream with StreamWriter vs Convert.ToBase64String()
根據Alexei的反饋,問題得到了簡化:
如何使用緩沖的Stream方法將CryptoStream的內容(使用ToBase64Transform)轉換為StreamWriter(Unicode編碼)而不使用Convert.ToBase64String()?
注意:調用Convert.ToBase64String()會引發OutOfMemoryException,因此需要使用緩沖/流方法進行轉換。
您可能應該實現自定義Stream
,而不是TextWriter 。 編寫流比編寫器容易得多(例如將流傳遞到壓縮流)。
要創建自定義流,請從Stream
派生並至少實現Write
和Flush
(如果需要R / W流,則可以執行Read
)。 其余部分或多或少是可選的,取決於您的其他需求,定期復制到其他流不需要其他任何內容。
在構造函數中,將內部流傳遞給您以進行寫入。 Base64始終會產生ASCII字符,因此將帶有或不帶有BOM的UTF-8輸出直接寫到流中應該很容易,但是如果要指定編碼,則可以在內部用StreamWriter
包裝內部流。
在您的Write
實現緩沖區數據中,直到獲得足夠的字節以具有3字節的倍數的塊(即300),然后在該部分上調用Convert.ToBase64String
。 確保不要松動尚未轉換的部分。 由於Base64將3字節轉換為4個字符,因此以3的倍數大小的塊進行轉換將永遠不會在末尾添加=
/ ==
填充,並且可以與下一個塊連接。 因此,將轉換后的部分寫入內部流/寫入器。 請注意,您希望將塊大小限制為相對較小的大小,例如3*10000
以避免在大對象堆上分配塊。
在Flush
確保轉換最后一個未寫入的字節(這將是最后一個帶有=
padding的字節),並將其也寫入流中。
為了進行讀取,您可能需要格外小心,因為在Base64中允許使用空格,因此您無法讀取固定數量的字符並轉換為字節。 最簡單的方法是從StreamReader
按字符讀取並將每4個非空格的字符轉換為字節。
注意:您可以考慮直接從字節手動寫入/讀取Base64。 它會給您帶來一些性能上的好處,但是如果您不擅長移位,可能會很難。
請嘗試使用以下內容進行加密。 我正在使用fileName / filePath作為輸入。 您可以根據需要進行調整。 使用此程序,我已成功加密了超過1 GB的文件,沒有任何內存不足異常。
public bool EncryptUsingStream(string inputFileName, string outputFileName)
{
bool success = false;
// here assuming that you already have key
byte[] key = new byte[128];
SymmetricAlgorithm algorithm = SymmetricAlgorithm.Create();
algorithm.Key = key;
using (ICryptoTransform transform = algorithm.CreateEncryptor())
{
CryptoStream cs = null;
FileStream fsEncrypted = null;
try
{
using (FileStream fsInput = new FileStream(inputFileName, FileMode.Open, FileAccess.Read))
{
//First write IV
fsEncrypted = new FileStream(outputFileName, FileMode.Create, FileAccess.Write);
fsEncrypted.Write(algorithm.IV, 0, algorithm.IV.Length);
//then write using stream
cs = new CryptoStream(fsEncrypted, transform, CryptoStreamMode.Write);
int bytesRead;
int _bufferSize = 1048576; //buggersize = 1mb;
byte[] buffer = new byte[_bufferSize];
do
{
bytesRead = fsInput.Read(buffer, 0, _bufferSize);
cs.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
success = true;
}
}
catch (Exception ex)
{
//handle exception or throw.
}
finally
{
if (cs != null)
{
cs.Close();
((IDisposable)cs).Dispose();
if (fsEncrypted != null)
{
fsEncrypted.Close();
}
}
}
}
return success;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.