将CryptoStream转换为使用声明会使内存流为空

问题描述 投票:1回答:1

使用C#加密文本时,我遇到了一个奇怪的问题。ReSharper(我同意)建议替换此代码上的using块:

public object GetEncryptedOrDefault(object value, ICryptoTransform encryptor)
{
    if (encryptor is null)
    {
        throw new ArgumentNullException(nameof(encryptor));
    }
    var isEncryptionNeeded = value != null;
    if (isEncryptionNeeded)
    {
        using var memoryStream = new MemoryStream();
        using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
        {
            using var writer = new StreamWriter(cryptoStream);
            var valueAsText = value.ToString();
            writer.Write(valueAsText);
        }

        var encryptedData = memoryStream.ToArray();
        var encryptedText = Convert.ToBase64String(encryptedData);
        return encryptedText;
    }

    return default;
}

对此简化的代码(注意使用声明而不是块):

public object GetEncryptedOrDefault(object value, ICryptoTransform encryptor)
{
    if (encryptor is null)
    {
        throw new ArgumentNullException(nameof(encryptor));
    }
    var isEncryptionNeeded = value != null;
    if (isEncryptionNeeded)
    {
        using var memoryStream = new MemoryStream();
        using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
        using var writer = new StreamWriter(cryptoStream);
        var valueAsText = value.ToString();
        writer.Write(valueAsText);

        var encryptedData = memoryStream.ToArray();
        var encryptedText = Convert.ToBase64String(encryptedData);
        return encryptedText;
    }

    return default;
}

嗯..第一个效果很好,并且能够加密文本。但是第二个不起作用! encryptedData为空,因此会产生一个空的encryptedText

我看不到问题。为什么?

c# memorystream cryptostream
1个回答
0
投票

由于writer的作用域不再局限于cryptoStream的using块,因此现在就在从函数返回之前将其处置(而不是在cryptoStream的作用域结束时处置)。但是它没有将其内容刷新到流中,因为您没有在其上调用Flush,并且其AutoFlush属性默认为false

public object GetEncryptedOrDefault(object value, ICryptoTransform encryptor)
{
    if (encryptor is null)
    {
        throw new ArgumentNullException(nameof(encryptor));
    }
    var isEncryptionNeeded = value != null;
    if (isEncryptionNeeded)
    {
        using var memoryStream = new MemoryStream();
        using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
        using var writer = new StreamWriter(cryptoStream);
        var valueAsText = value.ToString();
        writer.Write(valueAsText);
        writer.Flush();

        var encryptedData = memoryStream.ToArray();
        var encryptedText = Convert.ToBase64String(encryptedData);
        return encryptedText;
    }

    return default;
}

在您的第一个示例中,writer在用完要写入的流之前已被处置(因此冲刷其缓冲区),因此在尝试访问它时该流不会为空。

© www.soinside.com 2019 - 2024. All rights reserved.