简易文件打包程序

对指定目录下面的文件进行打包。

简易解包程序参考博客另外一篇文章:
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;
}

猜你喜欢

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