SharpZipLib icon indicating copy to clipboard operation
SharpZipLib copied to clipboard

TarOutputStream doesn't flush buffer on Finish()

Open dsoprea opened this issue 12 years ago • 3 comments

When you call Finish() on the TarOutputStream, it doesn't flush everything.

Finish():

    public void Finish()
    {
        if ( IsEntryOpen ) 
        {
            CloseEntry();
        }
        WriteEofBlock();
    }

However, Close() includes a buffer.Close() call:

    public override void Close()
    {
        if ( !isClosed )
        {
            isClosed = true;
            Finish();
            buffer.Close();
        }
    }

This effectively flushes the TarBuffer. The upshot is that, if you want to have all of the data flushed, you need to close the TarOutputStream, which will automatically close the Stream object that you gave it. The exception for this is with the GZIP functionality, whose GzipOutputStream has a IsStreamOwner property that provides you the option of -not- closing the base stream.

This means that in order to get all of the data out of the Stream, you need to either use a MemoryStream wrapped by GzipOutputStream, or use a FileStream so that you can recover the data after the mandatory close.

dsoprea avatar Aug 22 '13 20:08 dsoprea

For this scenario you should be setting IsStreamOwner = false on the TarOutputStream:

var ms = new MemoryStream();
var tos = new TarOutputStream(ms);
tos.IsStreamOwner = false;

// Write a bunch of entries...

tos.CloseEntry()

tos.Close();

danjarvis avatar Nov 18 '13 21:11 danjarvis

I'm going to label this a bug, but I think it's more of a documentation bug.

-Neil

McNeight avatar Apr 14 '16 21:04 McNeight

My suggestion would be to add the flush to Finish() as well but also mark it as deprecated, suggesting the combination of IsStreamOwner and Dispose() (preferably using a using scope)

piksel avatar Nov 22 '20 15:11 piksel