简易解包程序

对压缩包进行解压。

简易压缩程序请参考博客的另外一篇文章:
http://blog.csdn.net/yi_ming_he/article/details/77689405

解包方式:
根据打包建立的索引表,找到对应的文件信息,逐个释放出来即可。

使用方法:
1.可以直接运行UnpacketFiles.exe进行解包,只需要把files.pak文件放入和UnpacketFiles.exe同一级目录即可,生成的文件位于和UnpacketFiles.exe的同一级目录的output文件夹中(如果该文件夹不存在会自动创建)
2.另外一种解包方式是通过指定命令行参数指定打包的文件路径和解包的目录,如下图所示:
这里写图片描述

UnPacketFiles.h

#pragma once

using std::fstream;

struct MyFileData
{
    int nOffset;//文件相对于压缩包文件的偏移
    int nFileSize;//文件的Size
    int nFileNameLength;//文件名包含的字符个数
    CString strFileName;//文件名

    MyFileData()
    {
        nOffset = 0;
        nFileSize = 0;
        nFileNameLength = 0;
    }
};

class CUnPacketFiles
{
public:
    CUnPacketFiles();
    ~CUnPacketFiles();

    void UnPacketFiles(LPCTSTR lpInputFilePath, LPCTSTR lpOutDir);

private:
    void _GetPacketInfo(LPCTSTR lpInputFilePath);
    void _DoUnPacketFiles(LPCTSTR lpOutDir);
    void _PathAddBackSlach(CString& strPath);

private:
    int m_nIndexTableSize;//索引表Size
    int m_nIndexTableElementCount;//索引表包含元素个数
    std::vector<MyFileData> m_vecFileData;
    fstream m_file;
};

UnPacketFiles.cpp

#include "stdafx.h"
#include "UnPacketFiles.h"

CUnPacketFiles::CUnPacketFiles()
{
    m_nIndexTableSize = 0;
    m_nIndexTableElementCount = 0;
    m_vecFileData.clear();
}


CUnPacketFiles::~CUnPacketFiles()
{
    m_file.close();
}

void CUnPacketFiles::UnPacketFiles(LPCTSTR lpInputFilePath, LPCTSTR lpOutDir)
{
    if (NULL == lpInputFilePath || NULL == lpOutDir)
        return;

    _GetPacketInfo(lpInputFilePath);
    _DoUnPacketFiles(lpOutDir);
}

void CUnPacketFiles::_GetPacketInfo(LPCTSTR lpInputFilePath)
{
    CString strInputFilePath(lpInputFilePath);
    m_file.open(CW2A(strInputFilePath), std::ios::in | std::ios::binary);

    m_file.read((char *)&m_nIndexTableSize, sizeof(int));
    m_file.read((char *)&m_nIndexTableElementCount, sizeof(int));

    for (int i = 0; i < m_nIndexTableElementCount; i++)
    {
        MyFileData myFileData;
        m_file.read((char *)&myFileData.nOffset, sizeof(int));
        m_file.read((char *)&myFileData.nFileSize, sizeof(int));
        m_file.read((char *)&myFileData.nFileNameLength, sizeof(int));

        CStringA strTemp;
        m_file.read(strTemp.GetBuffer(myFileData.nFileNameLength), myFileData.nFileNameLength);
        strTemp.ReleaseBuffer(myFileData.nFileNameLength);
        myFileData.strFileName = CA2W(strTemp);

        m_vecFileData.push_back(myFileData);
    }
}

void CUnPacketFiles::_DoUnPacketFiles(LPCTSTR lpOutDir)
{
    CString strDir(lpOutDir);
    _PathAddBackSlach(strDir);

    fstream destFile;
    for (int i = 0; i < (int)m_vecFileData.size(); ++i)
    {
        CString strFilePath = strDir + m_vecFileData[i].strFileName;
        destFile.open(CW2A(strFilePath), std::ios::out | std::ios::binary);
        m_file.seekp(m_nIndexTableSize + 4 + m_vecFileData[i].nOffset, std::ios::beg);
        for (int m = 0; m < m_vecFileData[i].nFileSize; ++m)
        {
            destFile.put(m_file.get());
        }
        destFile.close();
    }
}

void CUnPacketFiles::_PathAddBackSlach(CString& strPath)
{
    CString strTemp;
    strTemp = strPath.Right(1);

    if (strTemp != _T("\\") && strTemp != _T("/"))
        strPath.Append(_T("\\"));
}

main.cpp

#include "stdafx.h"
#include "UnPacketFiles.h"

CString GetCurrentModuleDir()
{
    TCHAR szPath[MAX_PATH + 1] = { 0 };
    if (0 == ::GetModuleFileName((HMODULE)&__ImageBase, szPath, MAX_PATH))
        return L"";

    ::PathRemoveFileSpec(szPath);
    CString strDir = szPath;
    return strDir;
}

void CorrectPath(CString& strPath)
{
    strPath.Replace(_T('/'), _T('\\'));
    do
    {
        if (strPath.Find(_T("\\\\")) == -1)
            break;

        strPath.Replace(_T("\\\\"), _T("\\"));

    } while (true);
}

void PathRemoveFileSpec(CString& strPath)
{
    CorrectPath(strPath);
    int nPos = strPath.ReverseFind(_T('\\'));
    if (nPos == -1)
    {
        strPath.Empty();
    }
    else
    {
        strPath = strPath.Left(nPos);
    }
}

BOOL CreateDeepDirectory(LPCTSTR szPath)
{
    BOOL bRetCode = FALSE;
    CString strPath(szPath);

    if (GetFileAttributes(szPath) != INVALID_FILE_ATTRIBUTES)
        return TRUE;

    bRetCode = ::CreateDirectory(szPath, NULL);
    if (!bRetCode && ::GetLastError() != ERROR_ALREADY_EXISTS)
    {
        PathRemoveFileSpec(strPath);
        if (strPath.IsEmpty()) return FALSE;

        bRetCode = CreateDeepDirectory(strPath);
        if (!bRetCode) return FALSE;

        bRetCode = ::CreateDirectory(szPath, NULL);
        if (!bRetCode && ::GetLastError() != ERROR_ALREADY_EXISTS)
            return FALSE;
    }

    return TRUE;
}

void PathAddBackSlach(CString& strPath)
{
    CString strTemp;
    strTemp = strPath.Right(1);

    if (strTemp != _T("\\") && strTemp != _T("/"))
        strPath.Append(_T("\\"));
}

int _tmain(int argc, _TCHAR* argv[])
{
    CString strInputFilePath = GetCurrentModuleDir() + L"\\files.pak";
    CString strOutDir = GetCurrentModuleDir() + L"\\output\\";
    if (argc == 3)
    {
        strInputFilePath = argv[1];
        strOutDir = argv[2];
    }

    PathAddBackSlach(strOutDir);
    CreateDeepDirectory(strOutDir);

    CUnPacketFiles files;
    files.UnPacketFiles(strInputFilePath, strOutDir);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yi_ming_he/article/details/77689453
今日推荐