0

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

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

我可以在块Utils.GetMD5Hash(stream);外,块内有如下所示的等价物,using目的是避免在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);
    }
}
4

2 回答 2

1

这是一个完整的答案,MemoryStream正如Petter Hesselberg在他的回答中所建议的那样。记下我必须遇到的一些棘手的情况,以执行我想做的事情:(1)确保fileStream使用块设置为 Disposable using,以及(2)确保在使用它之前MemoryStream设置为 start with ,两者都是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);
        }
    }
}
于 2016-01-27T12:20:46.203 回答
1

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

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,因此您实际上不太可能需要读取物理磁盘来计算哈希。性能提升可能不是您想象的那样。

于 2016-01-27T00:02:43.473 回答