Пример #1
0
        /// <summary>
        /// 读取HPK头文件并
        /// </summary>
        /// <param name="file"></param>
        /// <param name="hpkFile"></param>
        /// <param name="files"></param>
        /// <returns>如果成功,则返回true</returns>
        private bool ReadHeader(FileInfo file, out HpkFile hpkFile, out List <FileData> files)
        {
            hpkFile = new HpkFile();
            files   = new List <FileData>();
            using (FileStream fileReader = file.OpenRead())
            {
                using (BinaryReader binReader = new BinaryReader(fileReader))
                {
                    byte[] magic = binReader.ReadBytes(4);
                    if (!ByteCompare(magic, hpkFile.Magic))
                    {
                        Console.WriteLine("所选文件不是HPK文件");
                        return(false);
                    }
                    hpkFile.FileCount      = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.CompressedSize = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.NameEnd        = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.NameStart      = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.BaseOffset     = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.Version        = DataConverter.BigEndian.GetInt32(binReader.ReadBytes(4), 0);


                    //遍历读取每个文件的控制信息
                    binReader.ReadBytes(4);//跳过4个空的数据
                    for (int i = 0; i < hpkFile.FileCount; i++)
                    {
                        FileData fileData = new FileData();
                        fileData.HashData   = binReader.ReadBytes(0x10);
                        fileData.Offset     = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                        fileData.Size       = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                        fileData.NameOffset = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                        fileData.Unknown    = binReader.ReadBytes(4);
                        files.Add(fileData);
                        long currentPosition = fileReader.Position;//记录当前位置
                        uint namePosition    = hpkFile.NameStart + fileData.NameOffset;
                        fileReader.Seek(namePosition, SeekOrigin.Begin);
                        List <byte> nameData = new List <byte>();
                        while (binReader.PeekChar() != 0)
                        {
                            nameData.Add(binReader.ReadByte());
                        }
                        fileData.FilePath = Encoding.UTF8.GetString(nameData.ToArray());
                        //还原位置
                        fileReader.Seek(currentPosition, SeekOrigin.Begin);
                    }
                }
            }

            return(true);
        }
Пример #2
0
        public void Unpack(FileInfo file)
        {
            //将解包出来的文件全部放入这个basePath下
            string basePath = file.Name.Replace(file.Extension, "");

            HpkFile         hpkFile = null;
            List <FileData> files   = null;

            if (ReadHeader(file, out hpkFile, out files))
            {
                using (FileStream fileReader = file.OpenRead())
                {
                    foreach (var single in files)
                    {
                        uint filePos = single.Offset + hpkFile.BaseOffset;
                        fileReader.Seek(filePos, SeekOrigin.Begin);
                        byte[] data = new byte[single.Size];
                        fileReader.Read(data, 0, (int)single.Size);

                        string savePath = Path.Combine(basePath, single.FilePath);
                        string tempPath = savePath.Substring(0, savePath.LastIndexOf("/"));
                        if (!Directory.Exists(tempPath))
                        {
                            Directory.CreateDirectory(tempPath);
                        }
                        File.WriteAllBytes(savePath, data);
                    }

                    //完成之后,将现有头文件写入解压的根目录
                    fileReader.Seek(0, SeekOrigin.Begin);
                    byte[] header = new byte[hpkFile.BaseOffset];
                    fileReader.Read(header, 0, (int)hpkFile.BaseOffset);
                    File.WriteAllBytes(Path.Combine(basePath, "record.dat"), header);
                }
            }
        }
Пример #3
0
        public void Pack(DirectoryInfo directory)
        {
            string basePath = directory.Name;

            HpkFile         hpkFile = null;
            List <FileData> files   = null;

            FileInfo recordFile = new FileInfo(Path.Combine(basePath, "record.dat"));

            if (ReadHeader(recordFile, out hpkFile, out files))
            {
                using (MemoryStream allMemory = new MemoryStream())
                {
                    using (MemoryStream fileMemory = new MemoryStream())
                    {
                        //遍历文件进行读取并写入内存
                        bool isFirst = true;
                        for (int i = 0; i < files.Count; i++)
                        {
                            string savePath = Path.Combine(basePath, files[i].FilePath);
                            byte[] data     = File.ReadAllBytes(savePath);
                            fileMemory.Write(data, 0, data.Length);

                            //修改FileData记录的文件大小
                            files[i].Size = (uint)data.Length;
                            //修改偏移位置
                            if (isFirst)
                            {
                                files[i].Offset = 0;
                                isFirst         = false;
                            }
                            else
                            {
                                files[i].Offset = files[i - 1].Size + files[i - 1].Offset;
                            }
                        }

                        //开始建立头文件
                        allMemory.Write(hpkFile.Magic, 0, 4);
                        allMemory.Write(DataConverter.BigEndian.GetBytes(hpkFile.FileCount), 0, 4);
                        uint compressedSize = (uint)(hpkFile.BaseOffset + fileMemory.Length);
                        allMemory.Write(DataConverter.BigEndian.GetBytes(compressedSize), 0, 4);
                        allMemory.Write(DataConverter.BigEndian.GetBytes(hpkFile.NameEnd), 0, 4);
                        allMemory.Write(DataConverter.BigEndian.GetBytes(hpkFile.NameStart), 0, 4);
                        allMemory.Write(DataConverter.BigEndian.GetBytes(hpkFile.BaseOffset), 0, 4);
                        allMemory.Write(DataConverter.BigEndian.GetBytes(hpkFile.Version), 0, 4);
                        allMemory.Write(new byte[4], 0, 4);

                        //遍历写入文件控制信息
                        foreach (var single in files)
                        {
                            allMemory.Write(single.HashData, 0, 0x10);
                            allMemory.Write(DataConverter.BigEndian.GetBytes(single.Offset), 0, 4);
                            allMemory.Write(DataConverter.BigEndian.GetBytes(single.Size), 0, 4);
                            allMemory.Write(DataConverter.BigEndian.GetBytes(single.NameOffset), 0, 4);
                            allMemory.Write(single.Unknown, 0, 4);
                        }

                        //写入文件名称
                        foreach (var single in files)
                        {
                            byte[] pathData = Encoding.UTF8.GetBytes(single.FilePath);
                            allMemory.Write(pathData, 0, pathData.Length);
                            allMemory.WriteByte(0);
                        }

                        //补0
                        int zeroCount = (int)(hpkFile.BaseOffset - allMemory.Length);
                        for (int i = 0; i < zeroCount; i++)
                        {
                            allMemory.WriteByte(0);
                        }

                        //最后写入文件数据
                        allMemory.Write(fileMemory.ToArray(), 0, (int)fileMemory.Length);
                        File.WriteAllBytes(basePath + ".hpk", allMemory.ToArray());
                    }
                }
            }
        }
Пример #4
0
        /// <summary>
        /// 读取HPK头文件并
        /// </summary>
        /// <param name="file"></param>
        /// <param name="hpkFile"></param>
        /// <param name="files"></param>
        /// <returns>如果成功,则返回true</returns>
        private bool ReadHeader(FileInfo file, out HpkFile hpkFile, out List<FileData> files)
        {
            hpkFile = new HpkFile();
            files = new List<FileData>();
            using (FileStream fileReader = file.OpenRead())
            {
                using (BinaryReader binReader = new BinaryReader(fileReader))
                {
                    byte[] magic = binReader.ReadBytes(4);
                    if (!ByteCompare(magic, hpkFile.Magic))
                    {
                        Console.WriteLine("所选文件不是HPK文件");
                        return false;
                    }
                    hpkFile.FileCount = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.CompressedSize = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.NameEnd = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.NameStart = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.BaseOffset = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                    hpkFile.Version = DataConverter.BigEndian.GetInt32(binReader.ReadBytes(4), 0);

                    //遍历读取每个文件的控制信息
                    binReader.ReadBytes(4);//跳过4个空的数据
                    for (int i = 0; i < hpkFile.FileCount; i++)
                    {
                        FileData fileData = new FileData();
                        fileData.HashData = binReader.ReadBytes(0x10);
                        fileData.Offset = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                        fileData.Size = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                        fileData.NameOffset = DataConverter.BigEndian.GetUInt32(binReader.ReadBytes(4), 0);
                        fileData.Unknown = binReader.ReadBytes(4);
                        files.Add(fileData);
                        long currentPosition = fileReader.Position;//记录当前位置
                        uint namePosition = hpkFile.NameStart + fileData.NameOffset;
                        fileReader.Seek(namePosition, SeekOrigin.Begin);
                        List<byte> nameData = new List<byte>();
                        while (binReader.PeekChar() != 0)
                        {
                            nameData.Add(binReader.ReadByte());
                        }
                        fileData.FilePath = Encoding.UTF8.GetString(nameData.ToArray());
                        //还原位置
                        fileReader.Seek(currentPosition, SeekOrigin.Begin);
                    }
                }
            }

            return true;
        }