public static void PkgToZip(PkgInfo pkgInfo, string zipFilePath) { Console.ForegroundColor = ConsoleColor.DarkGreen; using (FileStream pkgFileStream = new FileStream(pkgInfo.FilePath, FileMode.Open, FileAccess.Read)) using (FileStream zipFileStream = new FileStream(zipFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) using (ZipArchive zipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Create)) { int filesPacked = 0; foreach (var file in pkgInfo.Files) { try { //Создаем новое вхождение в архиве с нужным названием var fileEntry = zipArchive.CreateEntry(file.Path, CompressionLevel.NoCompression); using (Stream writer = Stream.Synchronized(fileEntry.Open())) { byte[] binBytes = new byte[file.Lenght]; //Переходим в нужную позицию в пакете pkgFileStream.Seek(pkgInfo.Offset + file.Offset, SeekOrigin.Begin); int readedCount = pkgFileStream.Read(binBytes, 0, file.Lenght); if (readedCount != file.Lenght) //Кидаемься молотком, если вдруг насокячили с чтением { throw new ArgumentOutOfRangeException($"File lenght: {file.Lenght}, but readed: {readedCount}"); } //Записываем в архив writer.Write(binBytes, 0, readedCount); writer.Flush(); } //Успешно перепаковали filesPacked++; Console.WriteLine($"{filesPacked}:> {file.Path}"); } catch (Exception ex) { //Словили молоток! Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"!> Exception {ex.Message} catched at file: {file.Path}!"); Console.ForegroundColor = ConsoleColor.DarkGreen; } } //Сообщаем об результате if (filesPacked == pkgInfo.FilesCount) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"All {pkgInfo.FilesCount} pkg files repacked to zip successfully!"); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Only {filesPacked} of {pkgInfo.FilesCount} pkg files repacked to zip!"); Console.ForegroundColor = ConsoleColor.Gray; } } }
/// <summary> /// Создать информацию о пакете для его последуещего создания из zip архива /// </summary> /// <param name="zipFilePath">Путь к zip файлу</param> /// <param name="pkgFilePath">Путь к пакету который будет создан</param> /// <returns></returns> public static PkgInfo CreatePkgInfoFromZip(string zipFilePath, string pkgFilePath) { PkgInfo pkgInfo = new PkgInfo(); using (var zipFileStream = new FileStream(zipFilePath, FileMode.Open, FileAccess.Read)) using (var zipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Read)) { pkgInfo.Signature = "PKGV0001"; pkgInfo.FilePath = pkgFilePath; pkgInfo.FilesCount = zipArchive.Entries.Count; //Прекомпутируем оффсет начального файла pkgInfo.Offset += 4 + pkgInfo.Signature.Length + 4; //signatureStringLenght + "signatureString" + filesCountInt foreach (var entry in zipArchive.Entries) { pkgInfo.Offset += (4 + entry.FullName.Length + 4 + 4); //pathStringLenght + "pathString" + offsetInt + lenghtInt } //Генерируем дерево файлов int filesOffset = 0; foreach (var entry in zipArchive.Entries) { pkgInfo.Files.Add(new PkgInfo.FileInfo() { Path = entry.FullName, Lenght = (int)(entry.Length), Offset = filesOffset, }); filesOffset += (int)(entry.Length); } } //Возвращяем готовую информацию об пакете return(pkgInfo); }
/// <summary> /// Получить информацию об пакете /// </summary> /// <param name="pkgFilePath">Путь к файлу пакета .pkg/param> /// <returns></returns> public static PkgInfo ReadPkgInfo(string pkgFilePath) { PkgInfo pkgInfo = new PkgInfo(pkgFilePath); using (var pkgFileStream = new FileStream(pkgFilePath, FileMode.Open, FileAccess.Read)) using (var br = new BinaryReader(pkgFileStream)) { //Читаем сигнатуру файла int maybeSignatureLenght = br.ReadInt32(); pkgInfo.Signature = new string(br.ReadChars(8)); if (pkgInfo.Signature != "PKGV0001") //Проверяем что это PKGV0001? { throw new InvalidDataException("Given file is not 'PKGV0001'!"); //Нас обманули! } //Читаем кол. файлов в пакете pkgInfo.FilesCount = br.ReadInt32(); //Сквозь все файлы в пакете for (int i = 0; i < pkgInfo.FilesCount; i++) { string path = new string(br.ReadChars(br.ReadInt32())); int offset = br.ReadInt32(); int lenght = br.ReadInt32(); pkgInfo.Files.Add(new PkgInfo.FileInfo() { Path = path, Offset = offset, Lenght = lenght }); } //Получаем начало содержимого файлов pkgInfo.Offset = (int)(br.BaseStream.Position); } //Возвращяем полученную информацию об пакете return(pkgInfo); }
public PkgConverter(string pkgFilePath, string zipFilePath, bool pkgToZip) { this._pkgToZip = pkgToZip; if (pkgToZip) { if (!File.Exists(pkgFilePath)) //Check exists pkg file? { throw new PkgConverterException(new FileNotFoundException(pkgFilePath), Error.PKG_FILE_NOT_FOUND); } _pkgInfo = new PkgInfo(pkgFilePath); //Creating file streams try { _pkgFileStream = new FileStream(pkgFilePath, FileMode.Open, FileAccess.Read); _zipFileStream = new FileStream(zipFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); } catch (Exception ex) { throw new PkgConverterException(ex, Error.FAILED_TO_CREATE_FILE_STREAM); } //Create zip archive try { _zipArchive = new ZipArchive(_zipFileStream, ZipArchiveMode.Create); } catch (Exception ex) { throw new PkgConverterException(ex, Error.FAILED_TO_CREATE_ZIP_ARCHIVE); } } else { if (!File.Exists(zipFilePath)) //Check exists pkg file? { throw new PkgConverterException(new FileNotFoundException(zipFilePath), Error.ZIP_FILE_NOT_FOUND); } _pkgInfo = new PkgInfo(pkgFilePath); //Creating file streams try { _zipFileStream = new FileStream(zipFilePath, FileMode.Open, FileAccess.ReadWrite); _pkgFileStream = new FileStream(pkgFilePath, FileMode.OpenOrCreate, FileAccess.Write); } catch (Exception ex) { throw new PkgConverterException(ex, Error.FAILED_TO_CREATE_FILE_STREAM); } //Create zip archive try { _zipArchive = new ZipArchive(_zipFileStream, ZipArchiveMode.Read); } catch (Exception ex) { throw new PkgConverterException(ex, Error.FAILED_TO_OPEN_ZIP_ARCHIVE); } } }
public static void ZipToPkg(PkgInfo pkgInfo, string zipFilePath) { Console.ForegroundColor = ConsoleColor.DarkYellow; using (var pkgFileStream = new FileStream(pkgInfo.FilePath, FileMode.OpenOrCreate, FileAccess.Write)) using (var zipFileStream = new FileStream(zipFilePath, FileMode.Open, FileAccess.Read)) using (var zipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Read)) using (var pkgBinaryWriter = new BinaryWriter(pkgFileStream)) { //Сообщаем об прогрессе Console.WriteLine($"Writing main signature and files count..."); pkgBinaryWriter.Write(pkgInfo.Signature.Length); //Длина строки сигнатуры (наверное) pkgBinaryWriter.Write(pkgInfo.Signature.ToCharArray()); //Сигнатура файла (!Обязательно как массив символов!) //Записываем кол. файлов в архиве pkgBinaryWriter.Write(pkgInfo.FilesCount); Console.WriteLine($"Writing files tree..."); //Создаем дерево файлов foreach (var file in pkgInfo.Files) { //Записываем длину строки пути файла и саму строку pkgBinaryWriter.Write(file.Path.Length); pkgBinaryWriter.Write(file.Path.ToCharArray()); //(!Обязательно как массив символов!) //Записываем оффсет этого файла в пакете pkgBinaryWriter.Write(file.Offset); //Записываем длину файла pkgBinaryWriter.Write(file.Lenght); } Console.WriteLine($"Starting writing files data to pkg..."); Console.ForegroundColor = ConsoleColor.DarkGreen; //Наконец все файлы впихываем int filesPacked = 0; for (int i = 0; i < pkgInfo.Files.Count; i++) { var entry = zipArchive.Entries[i]; using (var stream = Stream.Synchronized(entry.Open())) { byte[] readedBytes = new byte[entry.Length]; int readedCount = stream.Read(readedBytes, 0, readedBytes.Length); if (readedCount != entry.Length) //Кидаемься молотком, если вдруг насокячили с чтением { throw new ArgumentOutOfRangeException($"File lenght: {entry.Length}, but readed: {readedCount}"); } //Пихуем файл в пакет pkgBinaryWriter.Write(readedBytes, 0, readedCount); } filesPacked++; Console.WriteLine($"{filesPacked}:> {entry.FullName}"); } //Сообщаем об результате if (filesPacked == pkgInfo.Files.Count) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"All {pkgInfo.FilesCount} zip files repacked to pkg successfully!"); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Only {filesPacked} of {pkgInfo.FilesCount} packed... Something went wrong!"); Console.ForegroundColor = ConsoleColor.Gray; } } }