从File.OpenRead()返回流

时间:2012-01-05 11:09:33

标签: c# filestream

我正在编写一个允许ASP.Net网站检索文件的WCF服务(基于this article)。我的问题是,当我返回流时,它是空白的。

为简单起见,我已将代码隔离到一个简单的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长度为12,587字节(文件的正确长度),但它只包含0' s。

如果我尝试,Word文档会毫无问题地打开,我错过了一些明显的东西吗?

5 个答案:

答案 0 :(得分:38)

你忘了寻求:

str.CopyTo(data);
data.Seek(0, SeekOrigin.Begin); // <-- missing line
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);

答案 1 :(得分:14)

选项:

  • 按照ken2k
  • 的建议使用data.Seek
  • 使用稍微简单的Position属性:

    data.Position = 0;
    
  • 使用ToArray中的MemoryStream来简化您的生活:

    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();
    }
}

请注意,此不会关闭输入流。

答案 2 :(得分:5)

您忘记重置内存流的位置:

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));
    }                     
}

答案 3 :(得分:3)

你需要

    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流。还有memoryStream,只是出于主要原因。

答案 4 :(得分:1)

尝试将代码更改为:

private void Test()
{            
    System.IO.MemoryStream data = new System.IO.MemoryStream(TestStream());

    byte[] buf = new byte[data.Length];
    data.Read(buf, 0, buf.Length);                       
}