从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.Seekbuild议使用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); }