Когда закрывать файловый поток - PullRequest
1 голос
/ 14 мая 2019

Я читаю файл в zip-файле, используя потоки, подобные этому:

public static Stream ReadFile(Models.Document document, string path, string password, string fileName)
        {
            FileStream fsIn = System.IO.File.OpenRead(Path.Combine(path, $"{document.guid}.crypt"));
            var zipFile = new ZipFile(fsIn)
            {
                //Password = password,
                IsStreamOwner = true
            };



                var zipEntry = zipFile.GetEntry(fileName);
                //zipEntry.AESKeySize = 256;
                Stream zipStream = zipFile.GetInputStream(zipEntry);
                return zipStream;
        }

У меня проблемы с закрытием файлового потока fsIn, так как он недоступен, когда я возвращаюсь из метода ReadFile, и если я закрываю его в методе, поток zipStream, который я возвращаю, будет закрыт. Как я могу закрыть fsIn, но все же прочитать поток данных, возвращенный из моего метода?

1 Ответ

2 голосов
/ 14 мая 2019

Вы должны изменить тип возвращаемого значения, чтобы он был объектом, который содержит как родительский FileStream, так и внутренний файловый поток, чтобы потребитель вашей функции мог закрыть оба потока в случае необходимости - в качестве альтернативы вы можете создать подкласс Streamс вашим собственным типом, который затем предполагает владение обоими потоками.Вероятно, проще сделать первое, так как в противном случае вам придется проксировать все Stream методы.

Примерно так:

sealed class ReadFileResult : IDisposable
    // (use a `sealed` class with a non-virtual Dispose method for simpler compliance with IDisposable)
{
    private readonly FileStream zipFileStream;
    public Stream InnerFileStream { get; }

    internal ReadFileResult( FileStream zipFileStream, Stream innerFileStream )
    {
        this.zipeFileStream = zipFileStream;
        this.InnerFileStream = innerFileStream;
    }

    public void Dispose()
    {
        this.InnerFileStream.Dispose();
        this.zipFileStream.Dispose();
    }
}

public static ReadFileResult ReadFile(Models.Document document, string path, string password, string fileName)
{
    // ...
    return new ReadFileResult( zipFileStream: fsIn, innerFileStream: zipStream );
}

Потребляется примерно так:

void Foo()
{
    using( ReadFileResult rfr = ReadFile( ... ) )
    {
        Stream s = rdr.InnerFileStream;

        // ..
    } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...