有没有办法在不关闭BaseStream的情况下关闭StreamWriter?

时间:2010-04-19 11:16:22

标签: c# stream dispose

我的根本问题是当usingDispose上调用StreamWriter时,它还会处理BaseStream(与Close相同的问题)。

我有一个解决方法,但正如您所看到的,它涉及复制流。有没有办法在不复制流的情况下这样做?

这样做的目的是将字符串(最初从数据库中读取)的内容放入流中,以便第三方组件可以读取该流。 NB :我无法更改第三方组件。

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    baseCopy.Seek(0, System.IO.SeekOrigin.Begin);
    return baseCopy;
}

用作

public void Noddy()
{
    System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
    My3rdPartyComponent.ReadFromStream(myStream);
}

理想情况下,我正在寻找一种名为BreakAssociationWithBaseStream的虚构方法,例如

public System.IO.Stream CreateStream_Alternate(string value)
{
    var baseStream = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        writer.BreakAssociationWithBaseStream();
    }
    return baseStream;
}

5 个答案:

答案 0 :(得分:104)

如果您使用的是.NET Framework 4.5或更高版本,则会有StreamWriter overload using which you can ask the base stream to be left open when the writer is closed

在4.5之前的早期版本的.NET Framework中,StreamWriter 假设它拥有该流。选项:

  • 不要处置StreamWriter;只是冲洗它。
  • 创建一个流包装器,忽略对Close / Dispose的调用,但代理其他所有内容。我在MiscUtil中有一个实现,如果你想从那里抓住它。

答案 1 :(得分:40)

.NET 4.5为此获得了新的方法!

http://msdn.microsoft.com/EN-US/library/gg712853(v=VS.110,d=hv.2).aspx

public StreamWriter(
    Stream stream,
    Encoding encoding,
    int bufferSize,
    bool leaveOpen
)

答案 2 :(得分:32)

只是不要在Dispose上致电StreamWriter。这个类是一次性的原因不是因为它拥有非托管资源,而是允许处理本身可能拥有非托管资源的流。如果底层流的生命在其他地方处理,则不需要处理编写器。

答案 3 :(得分:5)

内存流具有ToArray属性,即使在关闭流时也可以使用该属性。 无论Position属性如何,To Array都将流内容写入字节数组。 您可以根据您编写的流创建新流。

public System.IO.Stream CreateStream(string value)
{
    var baseStream = new System.IO.MemoryStream();
    var baseCopy = new System.IO.MemoryStream();
    using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
    {
        writer.Write(value);
        writer.Flush();
        baseStream.WriteTo(baseCopy); 
    }
    var returnStream = new System.IO.MemoryStream( baseCopy.ToArray());
    return returnStream;
}

答案 4 :(得分:1)

你需要创建StreamWriter的后代并覆盖它的dispose方法,总是将false传递给disposing参数,它会强制流编写器不关闭,StreamWriter只是在close方法中调用dispose,所以有不需要覆盖它(当然,如果你愿意,你可以添加所有构造函数,我只需要一个):

public class NoCloseStreamWriter : StreamWriter
{
    public NoCloseStreamWriter(Stream stream, Encoding encoding)
        : base(stream, encoding)
    {
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(false);
    }
}