Edw*_*vey 21 c# stream objectdisposedexception
我创建了一个MemoryStream,传递给CryptoStream写作.我希望CryptoStream加密,然后让MemoryStream我开放,然后阅读其他内容.但是一旦CryptoStream被处置,它MemoryStream也会被处置掉.
可以以某种方式打开CryptoStream基地MemoryStream吗?
using (MemoryStream scratch = new MemoryStream())
{
using (AesManaged aes = new AesManaged())
{
// <snip>
// Set some aes parameters, including Key, IV, etc.
// </snip>
ICryptoTransform encryptor = aes.CreateEncryptor();
using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write))
{
myCryptoStream.Write(someByteArray, 0, someByteArray.Length);
}
}
// Here, I'm still within the MemoryStream block, so I expect
// MemoryStream to still be usable.
scratch.Position = 0; // Throws ObjectDisposedException
byte[] scratchBytes = new byte[scratch.Length];
scratch.Read(scratchBytes,0,scratchBytes.Length);
return Convert.ToBase64String(scratchBytes);
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 14
作为第二种解决方案,您可以创建一个WrapperStream对象,它只是传递除Dispose/Close之外的每个调用.围绕内存流创建一个包装器,将包装器交给加密流,现在关闭加密流不会触及内存流.
Sco*_*ain 10
你可以,但你将无法使用using语句.您需要手动管理对象的处理,并且还需要调用FlushFinialBlock()以确保在处理之前将所有数据写入基础流.
完成所有流程后,您可以在最后一个块中处理所有等待的资源.
MemoryStream scratch = null;
AesManaged aes = null;
CryptoStream myCryptoStream = null;
try
{
scratch = new MemoryStream();
aes = new AesManaged();
// <snip>
// Set some aes parameters, including Key, IV, etc.
// </snip>
ICryptoTransform encryptor = aes.CreateEncryptor();
myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write);
myCryptoStream.Write(someByteArray, 0, someByteArray.Length);
//Flush the data out so it is fully written to the underlying stream.
myCryptoStream.FlushFinalBlock();
scratch.Position = 0;
byte[] scratchBytes = new byte[scratch.Length];
scratch.Read(scratchBytes,0,scratchBytes.Length);
return Convert.ToBase64String(scratchBytes);
}
finally
{
//Dispose all of the disposeable objects we created in reverse order.
if(myCryptoStream != null)
myCryptoStream.Dispose();
if(aes != null)
aes.Dispose();
if(scratch != null)
scratch.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
从.NET 4.7.2开始,还有第二个构造函数,其中添加了一个bool参数leaveOpen.如果将其设置为true,那么CryptoStream的dispose方法将不会在底层流上调用dispose.
此外,没有leaveOpen参数的其他构造函数只是将参数转发到leaveOpen设置为的新构造函数false.
MSDN
CryptoStream.Dispose(bool disposing)
事实证明,没有必要将using {}块分解为try {} finally {} ......最终,你只需要在using语句中使用FlushFinalBlock(),并将其中的任何内容嵌套在其中必要.
using (MemoryStream scratch = new MemoryStream())
{
using (AesManaged aes = new AesManaged())
{
// <snip>
// Set some aes parameters, including Key, IV, etc.
// </snip>
ICryptoTransform encryptor = aes.CreateEncryptor();
using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write))
{
myCryptoStream.Write(someByteArray, 0, someByteArray.Length);
myCryptoStream.FlushFinalBlock();
scratch.Flush(); // not sure if this is necessary
byte[] scratchBytes = scratch.ToArray();
return Convert.ToBase64String(scratchBytes);
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我的简单方案:
class NotClosingCryptoStream : CryptoStream
{
public NotClosingCryptoStream( Stream stream, ICryptoTransform transform, CryptoStreamMode mode )
: base( stream, transform, mode )
{
}
protected override void Dispose( bool disposing )
{
if( !HasFlushedFinalBlock )
FlushFinalBlock();
base.Dispose( false );
}
}Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4593 次 |
| 最近记录: |