从File.OpenRead()返回流
本文关键字:返回 File OpenRead | 更新日期: 2023-09-27 18:19:26
我正在编写一个WCF服务,该服务将允许ASP.Net网站检索文件(基于本文)。我的问题是,当我返回流时,它是空白的。
为了简单起见,我将代码隔离到一个简单的winforms应用程序中,试图找出返回流的问题所在,这就是代码:
private Stream TestStream()
{
Stream fs = File.OpenRead(@"c:'testdocument.docx");
return fs;
}
// This method converts the filestream into a byte array so that when it is
// used in my ASP.Net project the file can be sent using response.Write
private void Test()
{
System.IO.MemoryStream data = new System.IO.MemoryStream();
System.IO.Stream str = TestStream();
str.CopyTo(data);
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
}
这个代码的结果是buf
是12587字节长(文件的正确长度),但它只包含0。
Word文档打开时没有问题,如果我尝试它,我是否遗漏了一些明显的内容?
您忘记了Seek
:
str.CopyTo(data);
data.Seek(0, SeekOrigin.Begin); // <-- missing line
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
选项:
- 按照ken2k的建议使用
data.Seek
-
使用稍微简单一点的
Position
属性:data.Position = 0;
-
使用
MemoryStream
中的ToArray
调用,让您的生活从开始变得更简单byte[] buf = data.ToArray();
第三种选择是我更喜欢的方法。
请注意,您应该有一个using
语句来自动关闭文件流(对于MemoryStream
也是可选的),我会为System.IO
添加一个using指令,以使您的代码更干净:
byte[] buf;
using (MemoryStream data = new MemoryStream())
{
using (Stream file = TestStream())
{
file.CopyTo(data);
buf = data.ToArray();
}
}
// Use buf
你可能还想在Stream
上创建一个扩展方法,在一个地方为你做这件事,例如
public static byte[] CopyToArray(this Stream input)
{
using (MemoryStream memoryStream = new MemoryStream())
{
input.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
请注意,此不会关闭输入流。
您忘记重置内存流的位置:
private void Test()
{
System.IO.MemoryStream data = new System.IO.MemoryStream();
System.IO.Stream str = TestStream();
str.CopyTo(data);
// Reset memory stream
data.Seek(0, SeekOrigin.Begin);
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
}
更新:
还有一点需要注意:通常不忽略方法的返回值是值得的。一个更健壮的实现应该检查调用返回后读取了多少字节:
private void Test()
{
using(MemoryStream data = new MemoryStream())
{
using(Stream str = TestStream())
{
str.CopyTo(data);
}
// Reset memory stream
data.Seek(0, SeekOrigin.Begin);
byte[] buf = new byte[data.Length];
int bytesRead = data.Read(buf, 0, buf.Length);
Debug.Assert(bytesRead == data.Length,
String.Format("Expected to read {0} bytes, but read {1}.",
data.Length, bytesRead));
}
}
您需要
str.CopyTo(data);
data.Position = 0; // reset to beginning
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
由于您的Test()
方法是在模仿客户端,因此它应该是Close()
或Dispose()
str
流。还有记忆流,只是出了本金。
尝试将代码更改为:
private void Test()
{
System.IO.MemoryStream data = new System.IO.MemoryStream(TestStream());
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
}