1. 程式人生 > >簡易檔案打包程式

簡易檔案打包程式

對指定目錄下面的檔案進行打包。

簡易解包程式參考部落格另外一篇文章:
http://blog.csdn.net/yi_ming_he/article/details/77689453

打包方式:
把目錄下面的檔名,檔案大小,偏移位置,檔案內容,以索引形式儲存在打包檔案中

使用方法:

1.packetfiles.exe為打包程式
2.執行時使用管理員許可權
3.可以直接執行packetfiles.exe進行打包,只需要把需要打包的檔案放在與packetfiles.exe同一級的input目錄即可(如果沒有該目錄需要手動建立在把檔案扔進去),生成的打包檔案預設是files.pak,位於和packetfiles.exe檔案同一級目錄
4.另外一種打包方式是通過指定命令列引數設定打包的目錄和打包後的檔案路徑,如下圖所示:
這裡寫圖片描述

PacketFiles.h:

#pragma once

struct MyFileData
{
    int nOffset;//檔案相對於壓縮包檔案的偏移
    int nFileSize;//檔案的Size
    int nFileNameLength;//檔名包含的字元個數
    CString strFileName;//檔名
    CString strFilePath;//檔案路徑,用於把檔案打包進來

    MyFileData()
    {
        nOffset = 0;
        nFileSize = 0;
        nFileNameLength = 0
; } }; class CPacketFiles { public: CPacketFiles(); ~CPacketFiles(); void PacketFiles(LPCTSTR lpDir, LPCTSTR lpOutFilePath);//傳入需要打包的資料夾目錄 private: void _PathAddBackSlach(CString& strPath); void _GetFileInfo(LPCTSTR lpDir); void _GetPacketInfo(); void _DoPacketFiles(LPCTSTR lpOutFilePath); private
: int m_nIndexTableSize;//索引表Size int m_nIndexTableElementCount;//索引表包含元素個數 std::vector<MyFileData> m_vecFileData; };

PacketFiles.cpp

#include "stdafx.h"
#include "PacketFiles.h"

using std::fstream;

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

CPacketFiles::~CPacketFiles()
{
}

void CPacketFiles::PacketFiles(LPCTSTR lpDir, LPCTSTR lpOutFilePath)
{
    if (NULL == lpDir || NULL == lpOutFilePath)
        return;

    _GetFileInfo(lpDir);
    _GetPacketInfo();
    _DoPacketFiles(lpOutFilePath);
}

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

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

void CPacketFiles::_GetFileInfo(LPCTSTR lpDir)
{
    CString strDir(lpDir);
    CString strFindPath;
    WIN32_FIND_DATA fData;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    _PathAddBackSlach(strDir);
    strFindPath.Format(_T("%s*.*"), strDir);

    hFind = ::FindFirstFile(strFindPath, &fData);
    if (hFind == INVALID_HANDLE_VALUE)
        goto Exit0;

    do
    {
        if (0 == _tcscmp(fData.cFileName, _T(".")) ||
            0 == _tcscmp(fData.cFileName, _T("..")))
            continue;

        if (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            continue;
        }
        else
        {
            CString strFileName = fData.cFileName;
            CString strFilePath = strDir + strFileName;
            MyFileData myFileData;
            myFileData.nFileNameLength = strFileName.GetLength();
            myFileData.strFileName = strFileName;
            myFileData.strFilePath = strFilePath;

            fstream file;
            file.open(CW2A(strFilePath), std::ios::in | std::ios::binary);
            file.seekp(0, std::ios::end);
            std::streamoff len = file.tellp();
            myFileData.nFileSize = (int)len;
            file.close();

            m_vecFileData.push_back(myFileData);
        }
    } while (::FindNextFile(hFind, &fData) != 0);

Exit0:
    if (hFind != INVALID_HANDLE_VALUE)
        ::FindClose(hFind);
}

void CPacketFiles::_GetPacketInfo()
{
    m_nIndexTableElementCount = m_vecFileData.size();
    int nOffSet = 0;
    m_nIndexTableSize = 4;//這個是指檔案個數
    for (int i = 0; i < (int)m_vecFileData.size(); i++)
    {
        m_nIndexTableSize += (sizeof(int) + sizeof(int) + sizeof(int) + m_vecFileData[i].nFileNameLength);//前面3個分別是偏移,檔案大小,檔名長度
        m_vecFileData[i].nOffset = nOffSet;
        nOffSet += m_vecFileData[i].nFileSize;
    }
}

void CPacketFiles::_DoPacketFiles(LPCTSTR lpOutFilePath)
{
    CString strOutFilePath(lpOutFilePath);
    fstream dstFile;
    fstream srcFile;
    dstFile.open(CW2A(strOutFilePath), std::ios::out | std::ios::binary);
    dstFile.write((char *)&m_nIndexTableSize, sizeof(int));
    dstFile.write((char *)&m_nIndexTableElementCount, sizeof(int));

    for (int i = 0; i < (int)m_vecFileData.size(); i++)
    {
        dstFile.write((char *)&m_vecFileData[i].nOffset, sizeof(int));
        dstFile.write((char *)&m_vecFileData[i].nFileSize, sizeof(int));
        dstFile.write((char *)&m_vecFileData[i].nFileNameLength, sizeof(int));
        CString strFileName = m_vecFileData[i].strFileName;
        dstFile.write((char *)CW2A(strFileName), m_vecFileData[i].nFileNameLength);
    }

    for (int i = 0; i < (int)m_vecFileData.size(); i++)
    {
        srcFile.open(CW2A(m_vecFileData[i].strFilePath), std::ios::in | std::ios::binary);
        dstFile.seekp(m_nIndexTableSize + 4 + m_vecFileData[i].nOffset, std::ios::beg);//定位寫資料的起始位置
        for (int j = 0; j < m_vecFileData[i].nFileSize; j++)
            dstFile.put(srcFile.get());
        srcFile.close();
    }
    dstFile.close();
}

main.cpp

#include "stdafx.h"
#include "PacketFiles.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;
}

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

    CPacketFiles files;
    files.PacketFiles(strInputDir, strOutFilePath);
    return 0;
}