#c_sharp
Есть список файлов, как упаковать их в rar/zip, и получить строку где находится архив с этими файлами.
Ответы
Ответ 1
Есть класс ZipFile. Можно использовать его. Есть библиотеки DotNetZip или SharpZipLib.Ответ 2
В дополнение к предыдущему ответу: using (var zip = new ZipFile()) { // оставляем комментарий к архиву zip.Comment = "Archive created by " + User.Identity.Name + " at " + DateTime.Now; // добавляем незапароленный файл в архив zip.AddFile(HostingEnvironment.ApplicationPhysicalPath + "ReadMe.txt"); // устанавливаем пароль к архиву zip.Password = password; // добавляем файл в архив, этот файл будет доступен только с вводом пароля, т.к. выше был установлен пароль zip.AddFile(databaseFileName); // установка уровня сжатия zip.CompressionLevel = CompressionLevel.BestCompression; // сохраняем архив zip.Save(databaseFileName + ".zip"); } Распаковка архива: using (ZipFile zip = ZipFile.Read(zipFile)) zip.ExtractAll(siteFolder, existingFileAction); Работа библиотеки меня вполне устраивает, но при сжатии файлов в несколько гигабайт использовал: zip.UseZip64WhenSaving = Zip64Option.AsNecessary;Ответ 3
Приведу пример как упаковать "потоково" в zip. Мне нужна была поддержка NET2.0 и к тому же, хочу показать внутреннюю структуру файла. using System; using System.IO; public class Demo{ public static int ZipDeflate(System.IO.Stream dest, string FileName, System.IO.Stream src, System.IO.Stream tail,int offset){ /* zip-архив двупроходный, содержит тело и "хвост" нужно записать "все" файлы через ZipStore, хвост запишется в tail*/ System.IO.MemoryStream deflate = new MemoryStream(); UInt32[] CrcTable = new UInt32[256]; DateTime dt = DateTime.Now; byte[] buf = new byte[4096]; int i = 0, j = 0; uint Crc32 = 0 ^ 0xffffffff; int size = (FileName == null) ? 0 : (14 + 12 + 4 + FileName.Length); uint dt2 = (uint)((dt.Second / 2) | (dt.Minute << 5) | (dt.Hour << 11) | (dt.Day << 16) | (dt.Month << 21) | ((dt.Year - 1980) << 25)); /*DOS time*/ uint POLYNOMIAL = 0xEDB88320, remainder = 0; for (i = 1; i < 256; i++) { remainder = (uint)i; for (uint bit = 8; bit > 0; --bit) remainder = ((remainder & 1) != 0) ? ((remainder >> 1) ^ POLYNOMIAL) : (remainder >> 1); CrcTable[i] = remainder; } src.Position = 0; using (System.IO.Compression.DeflateStream ds = new System.IO.Compression.DeflateStream(deflate, System.IO.Compression.CompressionMode.Compress,true)) do{ i = src.Read(buf, 0, 4096); for (j = 0; j < i; j++) Crc32 = CrcTable[(Crc32 ^ buf[j]) & 0xff] ^ (Crc32 >> 8); ds.Write(buf,0,i); } while (i == 4096); deflate.Position=0; src.Position = 0; Crc32 ^= 0xffffffff; dest.Write(new byte[] { 0x50, 0x4B, 0x03, 4, 0x14 , 0, 0, 0 , 8/*deflate*/, 0 }, 0, 10); Buffer.BlockCopy(new uint[] { dt2, Crc32, (uint)deflate.Length /*compressed size*/,(uint) src.Length, (uint)FileName.Length }, 0, buf, 0, 20); dest.Write(buf,0, 20); dest.Write(System.Text.Encoding.UTF8.GetBytes(FileName), 0, FileName.Length); do { i = deflate.Read(buf, 0, 4096); /*Запись "тела" (deflate stream)*/ if (i != 0) dest.Write(buf, 0, i); Console.Write("len=" + i); size += i; } while (i == 4096); long len = (long)tail.Length; /*Обработка хвоста*/ int offs = 0; int count = 1; if (len != 0){ tail.Position = len - 12; tail.Read(buf, 0, 12); count = ((int)BitConverter.ToInt16(buf, 0)) + 1; offs = BitConverter.ToInt32(buf, 6); tail.Position = len - 22; /*Следующий central-dir */ }; count = count * 65536 + count; /*Запись central-dir*/ Buffer.BlockCopy(new uint[] { 0x2014B50,0x200B23,0x80000/*deflate*/, dt2, Crc32, (uint)deflate.Length,(uint) src.Length, (uint)FileName.Length,0, 0x81, 0,0 }, 0, buf, 0, 42); tail.Write(buf,0,42); tail.Write(BitConverter.GetBytes(offset),0, 4); /* ? */ tail.Write(System.Text.Encoding.UTF8.GetBytes(FileName), 0, FileName.Length); len = (int)tail.Length; /*Запись endof-centraldir*/ Buffer.BlockCopy(new int[] { 0x6054B50,0,count,(int)len,(int)(offs+size),0 }, 0, buf, 0, 22); tail.Write(buf, 0, 22); tail.Position = 0; return size; } public static void Main(string[] args){ Stream dest = System.IO.File.Create("1.zip"); MemoryStream mm = new MemoryStream(); MemoryStream tail = new MemoryStream(); //MemoryStream tail = new System.IO.MemoryStream(); mm.Write(new byte[] { 65,65,65,65,65,65,65,65,65,65 },0, 10); mm.Position = 0; int offs =ZipDeflate(dest,"1.txt",mm,tail,0); /*Запись файла*/ // mm.Position = 0; offs += ZipDeflate(dest,"2.txt",mm,tail,offs);/*Второй файл*/ dest.Write(tail.ToArray(),0,(int)tail.Length);// Запись "хвоста" dest.Close(); } } Информация про структуру zip тут http://www.sql.ru/forum/1053806/razbor-zip-fayla И для файла который получился приведу "разбор" структуры И напоследок особенности такого подхода: размер архива или "разжатого" файла в архиве - до 2Gb, русские имена - нет Если убрать deflate и поменять 8(deflate) на 0, архив будет stored. в NET 2.0 маленькие (до 1kb) файлы плохо пакуются, т.к. добавляется 100байтная шапка, но функциональность не теряется.
Комментариев нет:
Отправить комментарий