【问题标题】:Can I get file.OpenStreamForReadAsync() from file.OpenStreamForWriteAsync()?我可以从 file.OpenStreamForWriteAsync() 获取 file.OpenStreamForReadAsync() 吗?
【发布时间】:2016-01-26 22:59:35
【问题描述】:

我仍在学习读/写文件流的技巧,如果我正在寻找的是可行的,希望有人能提供帮助。

下面的代码调用 WebApi(注意第 2 行的 GetAsync())来获取图像文件 ID,并使用计算的 Md5Hash 将下载的文件保存到数据库。该代码工作正常,但为了提高效率,我想知道是否有可能从file.OpenStreamForWriteAsync() 获得file.OpenStreamForReadAsync()(不确定是否可行,但我可以看到一些在流上运行但没有运气的扩展方法到目前为止我所做的尝试)。如果可能的话,我可以避免保存文件并再次打开它,而是在 using (var fileStream = await file.OpenStreamForWriteAsync()){ ... } 块中调用 GetMD5Hash() 方法。

我可以在using 块之外,在块内部,在下面显示Utils.GetMD5Hash(stream); 的等价物,目的是避免在using 块之外打开文件吗?

var client = new HttpClient();
var response = await client.GetAsync(new Uri($"{url}{imageId}")); // call to WebApi; url and imageId defined earlier

if (response.IsSuccessStatusCode)
{
    using (var contentStream = await response.Content.ReadAsInputStreamAsync())
    {
        var stream = contentStream.AsStreamForRead();
        var file = await imagesFolder.CreateFileAsync(imageFileName, CreationCollisionOption.ReplaceExisting);
        using (var fileStream = await file.OpenStreamForWriteAsync())
        {
            await stream.CopyToAsync(fileStream, 4096);

            // >>>> At this point, from the Write fileStream, can I get the equivalent of file.OpenStreamForReadAsync() ??

        }

        var stream = await file.OpenStreamForReadAsync();
        string md5Hash = await Utils.GetMD5Hash(stream);
        await AddImageToDataBase(file, md5Hash);
    }
}

【问题讨论】:

    标签: c# windows-runtime uwp storagefile


    【解决方案1】:

    MemoryStream 是读/写的,所以如果你想做的只是计算哈希,这样的事情应该可以解决问题:

    var stream = contentStream.AsStreamForRead();
    using (var ms = new MemoryStream())
    {
        stream.CopyTo(ms);
        ms.Seek(0, SeekOrigin.Begin);
        string md5Hash = await Utils.GetMD5Hash(ms);
    }
    

    但既然你还是想保存文件(毕竟它已传递给AddImageToDataBase),请考虑

    • 保存到MemoryStream
    • 重置内存流
    • 将内存流复制到文件流中
    • 重置内存流
    • 计算哈希

    不过,我建议您进行性能测量。操作系统确实缓存了文件 I/O,因此您实际上不太可能需要读取物理磁盘来计算哈希值。性能提升可能不是您想象的那样。

    【讨论】:

    • 你让我走上了正轨,谢谢。我正在发布一个完整的答案。
    【解决方案2】:

    这是使用MemoryStream 的完整答案,正如Petter Hesselberg 在他的回答中所建议的那样。记下我必须遇到的一些棘手情况,以执行我想做的事情:(1)确保 fileStream 使用 using 块设为 Disposable,以及(2)确保 MemoryStream 已设置在使用之前以ms.Seek(0, SeekOrigin.Begin);开头,既用于保存文件,也用于移交用于计算MD5Hash的MemoryStream对象。

    var client = new HttpClient();
    var response = await client.GetAsync(new Uri($"{url}{imageId}")); // call to WebApi; url and imageId defined earlier
    
    if (response.IsSuccessStatusCode)
    {
        using (var contentStream = await response.Content.ReadAsInputStreamAsync())
        {
            var stream = contentStream.AsStreamForRead();
            var file = await imagesFolder.CreateFileAsync(imageFileName, CreationCollisionOption.ReplaceExisting);
    
            using (MemoryStream ms = new MemoryStream())
            {
                await stream.CopyToAsync(ms);
                using (var fileStream = await file.OpenStreamForWriteAsync())
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    await ms.CopyToAsync(fileStream);
                    ms.Seek(0, SeekOrigin.Begin); // rewind for next use below
                }
    
                string md5Hash = await Utils.GetMD5Hash(ms);
                await AddImageToDataBase(file, md5Hash);
            }
        }
    }
    

    【讨论】:

    • 出于好奇,您是否尝试过任何性能测量?
    • 我会这样做并报告。我现在被其他事情打断了。
    猜你喜欢
    • 2021-06-18
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    相关资源
    最近更新 更多