我可以从 file.OpenStreamForWriteAsync() 得到 file.OpenStreamForReadAsync() 吗?
Can I get file.OpenStreamForReadAsync() from file.OpenStreamForWriteAsync()?
我仍在学习 read/write 文件流的技巧,如果我正在寻找的东西可行,希望有人能提供帮助。
下面的代码调用 WebApi(注意第 2 行的 GetAsync()
)以获取图像文件 ID 并使用计算的 Md5Hash 将下载的文件保存到数据库。代码工作正常,但为了提高效率,我想知道是否有可能从 file.OpenStreamForWriteAsync()
中获取 file.OpenStreamForReadAsync()
(不确定是否可行,但我可以看到一些扩展方法在流,但到目前为止我所做的尝试没有运气)。如果可能的话,我可以避免保存文件并再次打开它,方法是在 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);
}
}
A MemoryStream
是 read/write,所以如果您只想计算哈希值,那么像这样的事情应该可以解决问题:
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
- 重置内存流
- 将内存流复制到文件流
- 重置内存流
- 计算哈希值
不过,我建议您进行性能测量。 OS 确实缓存文件 I/O,因此您实际上不太可能必须执行物理磁盘读取来计算哈希值。性能提升可能不是你想象的那样。
这是使用 MemoryStream
的完整答案,正如 Petter Hesselberg 在他的答案中所建议的那样。记下我不得不遇到的几个棘手的情况,做我想做的事情:(1)确保 fileStream
是一次性的 using
块,以及(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);
}
}
}
我仍在学习 read/write 文件流的技巧,如果我正在寻找的东西可行,希望有人能提供帮助。
下面的代码调用 WebApi(注意第 2 行的 GetAsync()
)以获取图像文件 ID 并使用计算的 Md5Hash 将下载的文件保存到数据库。代码工作正常,但为了提高效率,我想知道是否有可能从 file.OpenStreamForWriteAsync()
中获取 file.OpenStreamForReadAsync()
(不确定是否可行,但我可以看到一些扩展方法在流,但到目前为止我所做的尝试没有运气)。如果可能的话,我可以避免保存文件并再次打开它,方法是在 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);
}
}
A MemoryStream
是 read/write,所以如果您只想计算哈希值,那么像这样的事情应该可以解决问题:
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
- 重置内存流
- 将内存流复制到文件流
- 重置内存流
- 计算哈希值
不过,我建议您进行性能测量。 OS 确实缓存文件 I/O,因此您实际上不太可能必须执行物理磁盘读取来计算哈希值。性能提升可能不是你想象的那样。
这是使用 MemoryStream
的完整答案,正如 Petter Hesselberg 在他的答案中所建议的那样。记下我不得不遇到的几个棘手的情况,做我想做的事情:(1)确保 fileStream
是一次性的 using
块,以及(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);
}
}
}