Как перейти от byte [] к MemoryStream, распаковать, затем записать в FileStream - PullRequest
0 голосов
/ 05 марта 2019

Я не уверен, что я делаю неправильно.Файлы, которые я создаю после получения byte[] (то есть emailAttachment.Body) и передачи его в метод ExtractZipFile, преобразования его в MemoryStream, а затем его разархивирования, возврата в виде KeyValuePair и последующей записи в файл.используя FileStream.

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

Ниже приведены в том же классе

using Ionic.Zip;

var extractedFiles = ExtractZipFile(emailAttachment.Body);

foreach (KeyValuePair<string, MemoryStream> extractedFile in extractedFiles)
{                               
    string FileName = extractedFile.Key;
    using (FileStream file = new FileStream(CurrentFileSystem + 
    FileName.FileFullPath(),FileMode.Create, System.IO.FileAccess.Write))
    {
        byte[] bytes = new byte[extractedFile.Value.Length];
        extractedFile.Value.Read(bytes, 0, (int) xtractedFile.Value.Length);
        file.Write(bytes,0,bytes.Length);
        extractedFile.Value.Close();
     }
}


private Dictionary<string, MemoryStream> ExtractZipFile(byte[] messagePart)
{
    Dictionary<string, MemoryStream> result = new Dictionary<string,MemoryStream>();
    MemoryStream data = new MemoryStream(messagePart);
    using (ZipFile zip = ZipFile.Read(data))
    {
        foreach (ZipEntry ent in zip)
        {
            MemoryStream memoryStream = new MemoryStream();
            ent.Extract(memoryStream);
            result.Add(ent.FileName,memoryStream);
        }   
    }
    return result;
}

Есть что-то, что мне не хватает?Я не хочу сохранять оригинальный zip-файл, только извлеченные файлы из MemoryStream.Что я делаю не так?

Ответы [ 3 ]

0 голосов
/ 05 марта 2019

Я бы посоветовал вам очистить использование MemoryStream в вашем коде.

Я согласен, что вызов memoryStream.Position = 0; позволит этому коду работать правильно, но его легко пропустить, когдачтение и запись потоков памяти.

Лучше написать код, который позволит избежать ошибки.

Попробуйте:

private IEnumerable<(string Path, byte[] Content)> ExtractZipFile(byte[] messagePart)
{
    using (var data = new MemoryStream(messagePart))
    {
        using (var zipFile = ZipFile.Read(data))
        {
            foreach (var zipEntry in zipFile)
            {
                using (var memoryStream = new MemoryStream())
                {
                    zipEntry.Extract(memoryStream);
                    yield return (Path: zipEntry.FileName, Content: memoryStream.ToArray());
                }
            }
        }
    }
}

Тогда ваш код вызова будет выглядеть примерно так:

foreach (var extractedFile in ExtractZipFile(emailAttachment.Body))
{
    File.WriteAllBytes(Path.Combine(CurrentFileSystem, extractedFile.Path.FileFullPath()), extractedFile.Content);
}

Это намного меньше кода и гораздо больше шансов избежать ошибок.Предсказатель ошибок в коде номер один - это количество строк кода, которые вы пишете.

0 голосов
/ 05 марта 2019

Поскольку я нахожу много кода для простой операции, вот мои два цента.

using Ionic.Zip;

using (var s = new MemoryStream(emailAttachment.Body))
using (ZipFile zip = ZipFile.Read(s))
{
    foreach (ZipEntry ent in zip)
    {
        string path = Path.Combine(CurrentFileSystem, ent.FileName.FileFullPath())
        using (FileStream file = new FileStream(path, FileAccess.Write))
        {
            ent.Extract(file);
        }   
    }
}
0 голосов
/ 05 марта 2019

После записи в MemoryStream вы не устанавливаете позицию обратно в 0:

MemoryStream memoryStream = new MemoryStream();
ent.Extract(memoryStream);
result.Add(ent.FileName,memoryStream);

Из-за этого позиция потока будет в конце, когда вы попытаетесь читать из нее, иВы ничего не прочитаете.Обязательно перемотайте его:

memoryStream.Position = 0;

Кроме того, вам не нужно обрабатывать копию вручную.Просто позвольте методу CopyTo позаботиться об этом:

extractedFile.Value.CopyTo(file);
...