DotNetZip - чтение в память
Я собрал быстрый тест с использованием библиотеки DotNetZip, которая открывает zip-файл, полный.bmp-файлов, и преобразует их в формат.jpg.
До этого я записывал все файлы в папку, конвертировал их, сохранял файлы jpg и затем удалял исходные файлы bmp, что приводило к беспорядку.
Я не собираюсь сначала распаковывать их в памяти, конвертировать в jpg и затем сохранять.
Код работает, но просто не так быстро. Кто-нибудь может дать мне какие-либо указания относительно того, что я могу сделать, чтобы улучшить код, пожалуйста? Кроме того, поможет ли многопоточность?
string zipToUnpack = "c:\\test\\1000.zip";
string unpackDirectory = "c:\\temp\\";
string f = string.Empty;
Bitmap bm;
MemoryStream ms;
using (ZipFile zip = ZipFile.Read(zipToUnpack))
{
foreach (ZipEntry e in zip)
{
if (e.FileName.ToLower().IndexOf(".bmp") > 0)
{
ms = new MemoryStream();
e.Extract(ms);
try
{
bm = new Bitmap(ms);
f = unpackDirectory + e.FileName.ToLower().Replace(".bmp", ".jpg");
bm.Save(f, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
Console.WriteLine("File: " + e.FileName + " " + ex.ToString());
}
ms.Dispose();
}
}
}
Спасибо
1 ответ
В общем, DotNetZip является однопоточным. Вы можете открыть несколько архивов в нескольких потоках, но каждый архив только в одном потоке.
Если вы хотите подключить несколько процессоров или ядер, то я могу предложить вызвать QueueUserWorkItem для части, в которой вы преобразуете данные из MemoryStream в jpg.
Вызов ZipEntry.Extract() должен быть выполнен в одном потоке для всех записей. Это связано с тем, что Zipfile поддерживает один FileStream для всех прав на чтение, а несколько потоков, извлекающих записи, вызовут арифметические ошибки указателя файла.
Итак, как то так:
public class State
{
public string FileName;
public MemoryStream stream;
}
public void Run()
{
string unpackDirectory = "c:\\temp\\";
string zipToUnpack = "c:\\test\\1000.zip";
var ConvertImage = new WaitCallback( (o) => {
State s = o as State;
try
{
var bm = new Bitmap(s.stream);
var f = unpackDirectory + s.FileName.ToLower().Replace(".bmp", ".jpg");
bm.Save(f, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
Console.WriteLine("File: " + s.FileName + " " + ex.ToString());
}
});
using (ZipFile zip = ZipFile.Read(zipToUnpack))
{
foreach (ZipEntry e in zip)
{
if (e.FileName.ToLower().IndexOf(".bmp") > 0)
{
var ms = new MemoryStream();
e.Extract(ms);
ThreadPool.QueueUserWorkItem ( ConvertImage,
new State {
FileName = e.FileName, stream = ms }
});
}
}
}
}