从File.OpenRead()返回一个stream
我正在编写一个WCF服务,它将允许ASP.Net网站检索文件(基于本文 )。 我的问题是,当我返回stream,它是空白的。
为了简单起见,我将代码分离成一个简单的winforms应用程序,试图find返回stream的问题,这是代码:
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
的长度是12,587字节(文件的正确长度),但是它只包含0。
Word文档打开没有问题,如果我尝试一下,我错过了什么明显?
你忘了寻找:
str.CopyTo(data); data.Seek(0, SeekOrigin.Begin); // <-- missing line byte[] buf = new byte[data.Length]; data.Read(buf, 0, buf.Length);
选项:
-
data.Seek
build议使用data.Seek -
使用比较简单的
Position
属性:data.Position = 0;
-
在
MemoryStream
使用ToArray
调用使您的生活更简单:byte[] buf = data.ToArray();
第三个select将是我的首选方法。
请注意,您应该有一个using
语句来自动closures文件stream(也可以select使用MemoryStream
),并且为System.IO
添加using指令以使代码更清晰:
byte[] buf; using (MemoryStream data = new MemoryStream()) { using (Stream file = TestStream()) { file.CopyTo(data); buf = data.ToArray(); } } // Use buf
你也可能想在Stream
上创build一个扩展方法,在一个地方为你做这个,例如
public static byte[] CopyToArray(this Stream input) { using (MemoryStream memoryStream = new MemoryStream()) { input.CopyTo(memoryStream); return memoryStream.ToArray(); } }
请注意,这不会closuresinputstream。
您忘记了重置内存stream的位置:
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); }
更新:
还有一点需要注意:通常不会忽略方法的返回值。 更强大的实现应该检查在调用返回后有多less个字节被读取:
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
Stream。 而memoryStream也是,只是出于本质。
尝试将您的代码更改为:
private void Test() { System.IO.MemoryStream data = new System.IO.MemoryStream(TestStream()); byte[] buf = new byte[data.Length]; data.Read(buf, 0, buf.Length); }