поток памяти gzipstream в файл

Я пытаюсь сжать файлы JSON с помощью сжатия Gzip для отправки в другое место. Он должен обрабатывать 5 000–10 000 файлов в день, и мне не нужна сжатая версия файла на локальном компьютере (на самом деле они передаются в AWS S3 для долгосрочного архивирования).

Поскольку они мне не нужны, я пытаюсь сжать в поток памяти, а затем использовать его для записи в AWS, а не сжимать каждый из них на диск. Всякий раз, когда я пытаюсь это сделать, файлы ломаются (например, когда я открываю их в 7-Zip и пытаюсь открыть файл JSON внутри, я получаю сообщение «Файл ошибки данных поврежден»).

То же самое происходит, когда я пытаюсь записать поток памяти в локальный файл, поэтому я пока пытаюсь решить эту проблему. Вот код:

string[] files = Directory.GetFiles(@"C:\JSON_Logs");

foreach(string file in files)
{
    FileInfo fileToCompress = new FileInfo(file);
    using (FileStream originalFileStream = fileToCompress.OpenRead())
    {
        using (MemoryStream compressedMemStream = new MemoryStream())
        {
            using (GZipStream compressionStream = new GZipStream(compressedMemStream, CompressionMode.Compress))
            {
                originalFileStream.CopyTo(compressionStream);
                compressedMemStream.Seek(0, SeekOrigin.Begin);
                FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz");

                //Eventually this will be the AWS transfer, but that's not important here
                compressedMemStream.WriteTo(compressedFileStream); 
            }
        }
    }      
}

person smullan    schedule 09.05.2016    source источник
comment
Он создал файл .gz. 7-Zip обычно читает файл .gz. Я пробовал делать это с файловым потоком вместо потока памяти, и он отлично работает.   -  person smullan    schedule 09.05.2016


Ответы (1)


Измените порядок ваших операторов using так, чтобы GZipStream определенно выполнялся к тому моменту, когда вы читаете содержимое потока памяти:

foreach(string file in files)
{
    FileInfo fileToCompress = new FileInfo(file);
    using (MemoryStream compressedMemStream = new MemoryStream())
    {
        using (FileStream originalFileStream = fileToCompress.OpenRead())
        using (GZipStream compressionStream = new GZipStream(
            compressedMemStream, 
            CompressionMode.Compress,
            leaveOpen: true))
        {
            originalFileStream.CopyTo(compressionStream);
        }
        compressedMemStream.Seek(0, SeekOrigin.Begin);

        FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz");
        //Eventually this will be the AWS transfer, but that's not important here
        compressedMemStream.WriteTo(compressedFileStream); 
    }
}

Утилизация ручья заботится о его промывке и закрытии.

person Jeroen Mostert    schedule 09.05.2016
comment
Не заметил ошибки аранжировки .. +1 - person Jeroen van Langen; 09.05.2016
comment
Затем я получаю системное исключение: не удается получить доступ к закрытому потоку в строке compressedMemStream.WriteTo (compressedFileStream); - person smullan; 09.05.2016
comment
@smullan: Упс. GZipStream думает, что владеет переданным ему потоком, что означает, что он закрывает MemoryStream из-под нас. Грубый. Мы говорим ему не делать этого, передав параметр leaveOpen. (Мы также могли бы исправить это, переставив больше кода, потому что MemoryStream можно прочитать после закрытия его через свой массив, но я думаю, что это более элегантно.) - person Jeroen Mostert; 09.05.2016