Правильное сжатие CSV с использованием GZIP Stream и Memory Stream

Я сжимаю CSV-файл, используя GZIPStream и MemoryStream, и заметил что-то странное в результирующем файле. Похоже, что CSV не распознается должным образом. Это отображается, когда файл прикреплен к электронному письму, но отлично работает при сохранении на рабочем столе Windows.

Вот текущий фрагмент, обрабатывающий часть gzip:

GZipStream gStream = null;
        MemoryStream mStream = null;
        MemoryStream mStream2 = null;
        try
        {
            if (attachment.Length > 0)
            {                    
                mStream = new MemoryStream();

                gStream = new GZipStream(mStream, CompressionMode.Compress);                    
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(attachment.ToString());
                gStream.Write(bytes, 0, bytes.Length);
                gStream.Close();

                mStream2 = new MemoryStream(mStream.ToArray());
                Attachment emailAttachement = new Attachment(mStream2, "myGzip.csv.gz", "application/x-Gzip");                                         
                mailMessage.Attachments.Add(emailAttachement);
            }

        }

person GeorgeU    schedule 14.02.2011    source источник
comment
Что показывает? Что повело себя неожиданно? Как выглядит код? что-нибудь? И что такое результирующий файл [sic], если вы используете поток памяти?   -  person Marc Gravell    schedule 15.02.2011
comment
Кстати, если бы мне пришлось угадывать вслепую: поток gzip не был закрыт до того, как вы вызвали ToArray() в потоке памяти   -  person Marc Gravell    schedule 15.02.2011
comment
Я включил код. Что мы замечаем, так это то, что когда файл GZIP открывается (при прикреплении к электронному письму), сжатый файл не является файлом .csv (каким-то образом).   -  person GeorgeU    schedule 15.02.2011


Ответы (3)


Я смог сжать gzip и отправить csv, используя приведенный ниже код. GZipStream не завершит запись, пока не будет вызван его метод Close(). Это происходит, когда блок using, создающий gzipStream, завершен. Несмотря на то, что вывод потока также закрывается после завершения использования блока, данные все еще можно извлечь из потока вывода с помощью методов ToArray() или GetBuffer(). Дополнительные сведения см. в этой записи блога.

public void SendEmailWithGZippedAttachment(string fromAddress, string toAddress, string subject, string body, string attachmentText)
{
        const string filename = "myfile.csv.gz";
        var message = new MailMessage(fromAddress, toAddress, subject, body);

        //Compress and save buffer
        var output = new MemoryStream();
        using (var gzipStream = new GZipStream(output, CompressionMode.Compress))
        {
            using(var input = new MemoryStream(Encoding.UTF8.GetBytes(attachmentText)))
            {
                input.CopyTo(gzipStream);
            }
        }
        //output.ToArray is still accessible even though output is closed
        byte[] buffer = output.ToArray(); 

        //Attach and send email
        using(var stream = new MemoryStream(buffer))
        {
            message.Attachments.Add(new Attachment(stream, filename, "application/x-gzip"));
            var smtp = new SmtpClient("mail.myemailserver.com") {Credentials = new NetworkCredential("username", "password")};
            smtp.Send(message);
        }
}
person rsbarro    schedule 15.02.2011
comment
Большое спасибо. Вы спасли мой день. Даже сброс GZipStream не работает. Просто хочу добавить: теперь у нас есть новый ctor GZipStream с логическим параметром, который говорит: live open my stream. - person MuiBienCarlota; 16.05.2013

Все предложенные ответы не сработали. Нашел ответ здесь:

Одним из ограничений является то, что вы не можете дать имя файлу, который вы помещаете в архив.

http://msdn.microsoft.com/en-us/magazine/cc163727.aspx

person GeorgeU    schedule 16.02.2011

GZipStream НЕ создает zip-архив; он просто реализует алгоритм сжатия.

См. этот пример MSDN для создания zip-файла: http://msdn.microsoft.com/en-us/library/ywf6dxhx.aspx

person Richard Schneider    schedule 15.02.2011