Windows Practice_文件_文件分割器(一)

文件分割的意义

有以下几点需要进行文件分割:

  • 以前的硬盘格式是FAT32,也是意味着最大的内存放的单个文件是4GB,如果文件超过4GB,就需要进行分割成小于4GB的文件才能存储到硬盘上;
  • 网络虚度比较慢,并且还会出现中断,一旦中断,下载的文件就会失效。

我们在做分割时候,除了考虑分割外,还需要考虑合并,否则分割也就没有意义了。

CFile函数注意事项

CFile默认打开的是文本格式,这不符合文件风格的要求,文件分割需要使用二进制进行读写。

一般来说:BYTE表示的数据,而char代表一个字符。

文件切割代码
BOOL CFileCutterDemoDlg::CutFile(const CString& strFolderName, const CString& strOriginalFileName, const UINT uFileCutSize)
{
    BOOL bRet = FALSE;

    CFile cFileRead(strFolderName + L"\\" + strOriginalFileName, CFile::modeRead | CFile::typeBinary);
    //const UINT FILESIZE = 10;

    DWORD dwFileCount = 0;

    while (true)
    {
        BYTE byteArray[uFileCutSize] = { 0 };
        DWORD dwReadNum = cFileRead.Read(byteArray, uFileCutSize);

        CString strCurWriteFileName;
        CString strTempWriteFileName;
        strCurWriteFileName.Format(L"%d.part", dwFileCount++);

        CString strWriteFilePath = strFolderName + L"\\" + strCurWriteFileName;

        FileHeader fileHeader = { 0 };
        wcscpy_s(fileHeader.strFlag, L"Po");

        if (dwReadNum < uFileCutSize)
        {
            strTempWriteFileName.Format(L"%d.part", dwFileCount - 2);
            wcscpy_s(fileHeader.strPrevFileName, strTempWriteFileName.GetString());
            wcscpy_s(fileHeader.strNextFileName, L"last");

            CFile cFileWrite(strWriteFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
            cFileWrite.Write(&fileHeader, sizeof(FileHeader));
            cFileWrite.Write(byteArray, dwReadNum);
            cFileWrite.Close();

            bRet = TRUE;
            break;
        }
        else
        {
            if (dwFileCount == 1)
            {
                // 说明是第一个文件,它的前面是没有文件的
                wcscpy_s(fileHeader.strPrevFileName, L"first");
                strTempWriteFileName.Format(L"%d.part", dwFileCount);
                wcscpy_s(fileHeader.strNextFileName, strTempWriteFileName.GetString());
            }
            else
            {
                strTempWriteFileName.Format(L"%d.part", dwFileCount - 2);
                wcscpy_s(fileHeader.strPrevFileName, strTempWriteFileName);
                strTempWriteFileName.Format(L"%d.part", dwFileCount);
                wcscpy_s(fileHeader.strNextFileName, strTempWriteFileName.GetString());
            }

            CFile cFileWrite(strWriteFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
            cFileWrite.Write(&fileHeader, sizeof(FileHeader));
            cFileWrite.Write(byteArray, dwReadNum);
            cFileWrite.Close();
        }
    }
    cFileRead.Close();

    return bRet;
}
文件合并代码
struct PARTFILEHEADER
{
    WORD m_wFlag;
    WCHAR m_strPrevFileName[100];
    WCHAR m_strNextFileName[100];
    UINT m_uSourceFileSize;
};

BOOL CFileCutterDemoDlg::MyFindFirstFileName(const CString &strFolderName, const CString &strCurFileName, CString &strFirstFile) const
{
    BOOL bRet = FALSE;
    CString strFilePath = strFolderName + L"\\" + strCurFileName;

    FileHeader fileHeader = { 0 };
    CFile file(strFilePath.GetString(), CFile::modeRead | CFile::typeBinary);
    file.Read(&fileHeader, sizeof(FileHeader));
    file.Close();
    while (true)
    {
        if (wcscmp(fileHeader.strFlag, L"Po") == 0)
        {
            if (wcscmp(fileHeader.strPrevFileName, L"first") == 0)
            {
                // 找到第一个文件名字
                strFilePath = strFolderName + L"\\" + fileHeader.strNextFileName;
                file.Open(strFilePath, CFile::modeRead | CFile::typeBinary);
                file.Read(&fileHeader, sizeof(FileHeader));
                file.Close();
                strFirstFile = fileHeader.strPrevFileName;
                bRet = TRUE;
                break;
            }
            else
            {
                // 更新文件头信息
                strFilePath = strFolderName + L"\\";
                strFilePath += fileHeader.strPrevFileName;
                file.Open(strFilePath.GetString(), CFile::modeRead|CFile::typeBinary);
                file.Read(&fileHeader, sizeof(FileHeader));
                file.Close();
            }
        }
        else
        {
            break;
        }
    }
    return bRet;
}

BOOL CFileCutterDemoDlg::MyFindAllFileName(const CString& strFolderName, const CString& strFirstFile, std::vector<CString> &vecFileName) const
{
    BOOL bRet = FALSE;

    CString strFileName = strFirstFile;
    CString strFilePath = strFolderName + L"\\" + strFileName;
    FileHeader fileHeader = { 0 };
    CFile file(strFilePath, CFile::modeRead | CFile::typeBinary);
    file.Read(&fileHeader, sizeof(FileHeader));
    file.Close();

    while (true)
    {
        if (wcscmp(fileHeader.strFlag, L"Po") == 0)
        {
            // 将当前的文件路径加入到vec中
            vecFileName.push_back(strFileName);

            if (wcscmp(fileHeader.strNextFileName, L"last") == 0)
            {
                bRet = TRUE;
                break;
            }

            // 更新header
            strFileName = fileHeader.strNextFileName;
            strFilePath = strFolderName + L"\\" + strFileName;
            file.Open(strFilePath, sizeof(FileHeader));
            file.Read(&fileHeader, sizeof(FileHeader));
            file.Close();
        }
        else
        {
            break;
        }
    }

    return bRet;
}

BOOL CFileCutterDemoDlg::MyFindFrontAllFileName(const CString& strFolderName, const CString& strCurFileName, std::vector<CString> &vecFrontAllFilePath) const
{
    BOOL bRet = FALSE;
    CString strFileName = strCurFileName;
    CString strFilePath = strFolderName + L"\\" + strFileName;
    FileHeader fileHeader = { 0 };
    CFile file(strFilePath, CFile::modeRead | CFile::typeBinary);
    file.Read(&fileHeader, sizeof(FileHeader));
    file.Close();

    while (true)
    {
        if (wcscmp(fileHeader.strFlag, L"Po") == 0)
        {
            // 将当前的文件路径加入到vec中
            vecFrontAllFilePath.push_back(strFileName);

            if (wcscmp(fileHeader.strPrevFileName, L"first") == 0)
            {
                bRet = TRUE;
                std::reverse(vecFrontAllFilePath.begin(), vecFrontAllFilePath.end());
                vecFrontAllFilePath.pop_back(); // 不包括当前的文件路径
                break;
            }

            // 更新header
            strFileName = fileHeader.strPrevFileName;
            strFilePath = strFolderName + L"\\" + strFileName;
            file.Open(strFilePath, sizeof(FileHeader));
            file.Read(&fileHeader, sizeof(FileHeader));
            file.Close();
        }
        else
        {
            break;
        }
    }

    return bRet;
}

BOOL CFileCutterDemoDlg::MyFindBackAllFileName(const CString& strFolderName, const CString& strCurFileName, std::vector<CString>& vecBackAllFilePath) const
{
    BOOL bRet = FALSE;
    CString strFileName = strCurFileName;
    CString strFilePath = strFolderName + L"\\" + strFileName;
    FileHeader fileHeader = { 0 };
    CFile file(strFilePath, CFile::modeRead | CFile::typeBinary);
    file.Read(&fileHeader, sizeof(FileHeader));
    file.Close();

    while (true)
    {
        if (wcscmp(fileHeader.strFlag, L"Po") == 0)
        {
            // 将当前的文件路径加入到vec中
            vecBackAllFilePath.push_back(strFileName);

            if (wcscmp(fileHeader.strNextFileName, L"last") == 0)
            {
                bRet = TRUE;
                break;
            }

            // 更新header
            strFileName = fileHeader.strNextFileName;
            strFilePath = strFolderName + L"\\" + strFileName;
            file.Open(strFilePath, sizeof(FileHeader));
            file.Read(&fileHeader, sizeof(FileHeader));
            file.Close();
        }
        else
        {
            break;
        }
    }

    return bRet;
}


void CFileCutterDemoDlg::MyMergeFile(const CString& strFolderName, const std::vector<CString> vecFileName) const
{
    CString strNewFilePath = strFolderName + L"\\" + L"mergeFile.txt";
    CFile fileNew(strNewFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
    const UINT FILESIZE = 10;
    for (auto file_name : vecFileName)
    {
        BYTE byteArray[FILESIZE] = { 0 };
        CString strFilePath = strFolderName + L"\\" + file_name;
        CFile file(strFilePath, CFile::modeRead | CFile::typeBinary);
        file.Seek(sizeof(FileHeader), CFile::begin);
        UINT uReadNum = file.Read(byteArray, FILESIZE);
        file.Close();

        fileNew.Write(byteArray, uReadNum);
    }
    fileNew.Close();
}

void CFileCutterDemoDlg::OnBnClickedButtonMerge()
{
    // 首先打开一个文件,读取信息头
    CFileDialog fileDlg(TRUE);
    if (fileDlg.DoModal() == IDOK)
    {
        // 是要合并的文件,可以开始遍历文件夹,找到所有的文件,然后按照顺序排列
        //首先分成两个方向, 首先,挨个向前遍历,找到第一个文件,如果找不到第一个文件,则文件缺失
        // 然后再从第一个文件向后遍历并记录文件路径,如果找不到最后文件,则文件缺失
        // 文件数量完整性标志
        CString strFirstFileName;
        std::vector<CString> vecAllFileName;
        std::vector<CString> vecFrontAllFileName;
        std::vector<CString> vecBackAllFileName;
        do
        {
             找第一个文件
            //if (!MyFindFirstFileName(fileDlg.GetFolderPath(), fileDlg.GetFileName(), strFirstFileName))
            //{
            //  // 没有找到第一个文件,查找失败
            //  MessageBox(TEXT("没有找到第一个文件名字!"));
            //  break;
            //}
            //if (!MyFindAllFileName(fileDlg.GetFolderPath(), strFirstFileName, vecAllFilePath))
            //{
            //  break;
            //}

            if (!MyFindFrontAllFileName(fileDlg.GetFolderPath(), fileDlg.GetFileName(), vecFrontAllFileName))
            {
                // 没有找到第一个文件,查找失败
                MessageBox(TEXT("没有找到第一个文件名字!"));
                break;
            }

            if (!MyFindBackAllFileName(fileDlg.GetFolderPath(), fileDlg.GetFileName(), vecBackAllFileName))
            {
                // 没有找到最后个文件,查找失败
                MessageBox(TEXT("没有找到最后个文件名字!"));
                break;
            }

            for (auto filePath : vecFrontAllFileName)
                vecAllFileName.push_back(filePath);

            for (auto filePath : vecBackAllFileName)
                vecAllFileName.push_back(filePath);


            MyMergeFile(fileDlg.GetFolderPath(), vecAllFileName);
        } while (false);
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值