tools : append file to file

来源:互联网 发布:淘宝网客服电话 编辑:程序博客网 时间:2024/05/29 13:41

今天有下载到2个文件, xx.7z.001, xx.7z.002

我只装了WinRar, 网上有资料说 可以用 copy /B, 合并文件后,  变成xx.7z, 然后用WinRar打开.


试了一下, 小文件合并, 用Copy /B 是可以的。

如果是大文件(这两个文件是600MB和100MB), Copy /B 失败


最初的想法是, 不安装7z解压程序, 直接写个小工具合并 .7z的分卷压缩文件到一个完整的7z文件, 然后用WinRar打开解压.

工具写好了, 运行 prjMergeFile.exe test.7z, 将xx.7z.000, ..., ... xx.7z.999之间的文件合并成一个xx.7z

D:\LsWorkDir\DebugTools\prjMergeFile\Release>prjMergeFile.exe test.7zusage : MergeFile file.postfixwill merge file file :.\file.postfix.001,.\file.postfix.002, .\file.postfix.XXX, to .\file.postfixif not need debug, press any key to continueargv[1] = [test.7z]strFileName = .\test.7z(llRdAll(670932347) == llWrAll(670932347)) is TRUEappend [.\test.7z.001] to [.\test.7z](llRdAll(130715875) == llWrAll(130715875)) is TRUEappend [.\test.7z.002] to [.\test.7z]mergeFile OKEND, press anykey to quit

手工算过size, 文件合并是正确的

xx.7z.001670,932,347xx.7z.002130,715,875xx.7z801,648,222

合并文件的工程文件

// prjMergeFile.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <windows.h>#include <tchar.h>#include <string>int mergeFile(const wchar_t * pcFileName);bool IsFileExist(const wchar_t * pcFileName);bool AppendSrcFileToDstFile(const wchar_t * pcFileDst,                             const wchar_t * pcFileSrc);bool AppendSrcFileToDstFile(HANDLE hFileDst,                             HANDLE hFileSrc);std::wstring StringFormatV(wchar_t * szFormat, ...);int _tmain(int argc, _TCHAR* argv[]){    int iRc =   S_OK;    _tprintf(   L"usage : MergeFile file.postfix\r\n"                L"will merge file file :\r\n"                L".\\file.postfix.001,\r\n"                L".\\file.postfix.002,\r\n "                L".\\file.postfix.XXX,\r\n "                L"to .\\file.postfix\r\n\r\n");        if (2 != argc)    {        _tprintf(L"2 != argc, please give parameter\r\n");        goto _tmain_END;    }    _tprintf(L"if not need debug, press any key to continue\r\n");    getwchar();    _tprintf(L"argv[1] = [%s]\r\n", argv[1]);   iRc = mergeFile(argv[1]);   _tprintf(L"mergeFile %s\r\n", (S_OK == iRc) ? L"OK" : L"FAILED");_tmain_END:    _tprintf(L"\r\nEND, press anykey to quit\r\n");    getwchar();return 0;}int mergeFile(const wchar_t * pcFileName){    int                     iRc             =   S_OK;    int                     iIndex          =   0;    std::wstring            strFileName;    std::wstring            strFileNameCur;    std::wstring::size_type nPos            =   std::wstring::npos;    strFileName = pcFileName;    nPos = strFileName.rfind(L'\\');    if (std::wstring::npos == nPos)    {        strFileName.insert(0, L".\\");        _tprintf(L"strFileName = %s\r\n", strFileName.c_str());    }    if (IsFileExist(pcFileName))    {        /// 防止损毁已经存在的用户文件        iRc = S_FALSE;        _tprintf(L"please remove [%s] and try again\r\n", pcFileName);        goto mergeFile_END;    }    for (iIndex = 0; iIndex <= 999; iIndex++)    {        strFileNameCur = StringFormatV(L"%s.%.3d", strFileName.c_str(), iIndex);        if (!IsFileExist(strFileNameCur.c_str()))            continue;        if (!AppendSrcFileToDstFile(    strFileName.c_str(),                                         strFileNameCur.c_str()))        {            _tprintf(L"FAILED : AppendSrcFileToDstFile(%s, %s)\r\n",                strFileName.c_str(),                strFileNameCur.c_str());            iRc = S_FALSE;            break;        }        else        {            _tprintf(L"append [%s] to [%s]\r\n",                 strFileNameCur.c_str(),                strFileName.c_str());        }    }mergeFile_END:    return iRc;}bool IsFileExist(const wchar_t * pcFileName){    HANDLE  hFile   = INVALID_HANDLE_VALUE;     hFile = ::CreateFile(        pcFileName,             // name of the write        GENERIC_READ,           // open for writing        0,                      // do not share        NULL,                   // default security        OPEN_EXISTING,          // overwrite existing        FILE_ATTRIBUTE_NORMAL,  // normal file        NULL);                  // no attr. template    if (INVALID_HANDLE_VALUE == hFile)         return false;    ::CloseHandle(hFile);    return true;}std::wstring StringFormatV(wchar_t * szFormat, ...){//入参为格式化的参数列表    size_t          nStrLen     =   0;    wchar_t *       pBufMsg     =   NULL;    std::wstring    strRc;    va_list         args;    va_start(args, szFormat);    nStrLen = _vsntprintf(NULL, 0, szFormat, args);    pBufMsg = new wchar_t[nStrLen + 1];    _ASSERT(pBufMsg);    ::ZeroMemory(pBufMsg, (nStrLen + 1) * sizeof(wchar_t));    nStrLen = _vsntprintf(pBufMsg, nStrLen, szFormat, args);    va_end(args);    strRc = pBufMsg;    delete []pBufMsg;    pBufMsg = NULL;    return strRc;}bool AppendSrcFileToDstFile(const wchar_t * pcFileDst,                             const wchar_t * pcFileSrc){    bool            bRc         =   false;    HANDLE          hFileDst    =   INVALID_HANDLE_VALUE;     HANDLE          hFileSrc    =   INVALID_HANDLE_VALUE;     LARGE_INTEGER   LISizeDst;    LISizeDst.QuadPart = (LONGLONG)0;    if (!IsFileExist(pcFileDst))    {        hFileDst = ::CreateFile(            pcFileDst,             // name of the write            GENERIC_WRITE,          // open for writing            0,                      // do not share            NULL,                   // default security            CREATE_NEW,             // overwrite existing            FILE_ATTRIBUTE_NORMAL,  // normal file            NULL);                  // no attr. template        if (INVALID_HANDLE_VALUE == hFileDst)             return false;        ::CloseHandle(hFileDst);        hFileDst = INVALID_HANDLE_VALUE;    }    /// open dst file    hFileDst = ::CreateFile(        pcFileDst,             // name of the write        GENERIC_WRITE,           // open for writing        0,                      // do not share        NULL,                   // default security        OPEN_EXISTING,          // overwrite existing        FILE_ATTRIBUTE_NORMAL,  // normal file        NULL);                  // no attr. template    if (INVALID_HANDLE_VALUE == hFileDst)         goto AppendSrcFileToDstFile_END;    if (!GetFileSizeEx(hFileDst, &LISizeDst))        goto AppendSrcFileToDstFile_END;    if (0 != LISizeDst.QuadPart)        SetFilePointer (hFileDst, 0, NULL, FILE_END) ;    /// open src file    hFileSrc = ::CreateFile(        pcFileSrc,             // name of the write        GENERIC_READ,           // open for writing        0,                      // do not share        NULL,                   // default security        OPEN_EXISTING,          // overwrite existing        FILE_ATTRIBUTE_NORMAL,  // normal file        NULL);                  // no attr. template    if (INVALID_HANDLE_VALUE == hFileSrc)         goto AppendSrcFileToDstFile_END;    /// read from src file, write to dst file    if (AppendSrcFileToDstFile(hFileDst, hFileSrc))        bRc = true;AppendSrcFileToDstFile_END:    if (INVALID_HANDLE_VALUE != hFileDst)        ::CloseHandle(hFileDst);    if (INVALID_HANDLE_VALUE != hFileSrc)        ::CloseHandle(hFileSrc);    return bRc;}bool AppendSrcFileToDstFile(HANDLE hFileDst,                             HANDLE hFileSrc){    LONGLONG    llRdAll  =   0;    LONGLONG    llWrAll  =   0;    bool    bRc     =   false;    DWORD   dwRdBk  =   0;    DWORD   dwWrBk  =   0;    BYTE    cBufRdBk[4096];    do     {        if (FALSE == ::ReadFile(hFileSrc,                                 cBufRdBk,                                 sizeof(cBufRdBk),                                 &dwRdBk,                                 NULL))        {            return false;        }        llRdAll += dwRdBk;        if (0 == dwRdBk)            break;        if (FALSE == ::WriteFile(hFileDst, cBufRdBk, dwRdBk, &dwWrBk, NULL))            return false;        llWrAll += dwWrBk;        if (dwRdBk != dwWrBk)            return false;    } while (1);    if (llRdAll > 0)    {        _tprintf(L"(llRdAll(%I64d) == llWrAll(%I64d)) is %s\r\n",            llRdAll,            llWrAll,            (llRdAll == llWrAll) ? L"TRUE" : L"FALSE");    }    return (llRdAll == llWrAll);}

但是合并后的xx.7z, 用WinRar打不开 :(

我装个7z解压, 看看能否打开这个.7z文件.


从7Zip主页(http://sourceforge.net/projects/sevenzip/?source=dlp)上下载了一个X64版本.


7zip也打不开合并后的单个.7z文件, 我高度怀疑每个.7z.xx分卷压缩的文件头上有解压标记和分卷文件合并信息, 

非第一个7z分卷压缩文件, 并不是单纯的为数据文件. 所以导致打不开.


作了实验,  装了7zip也打不开xx.7z.001文件. 初步判断此文件在下载过程中损坏或者下载点的xx.7z.00x就是坏的.

后续实验, 将一个很大的文件夹用7zip压缩成test.7z分卷文件, 每个分卷650MB, 加上口令

用7zip打开test.7z.002文件是失败的, 说明.7z.002文件中没有文件解压信息.

用7zip打开test.7z.001文件成功成功, 并且弹出口令框. 说明xx.7z.001文件确实是坏的. 晕倒啊~~


用此合并工具将test.7z.001和test.7z.002文件合并后, 用WinRar和7Zip均能打开.

说明本次合并工具是靠谱的~~


bool AppendSrcFileToDstFile(const wchar_t * pcFileDst, const wchar_t * pcFileSrc); 

AppendSrcFileToDstFile函数可以留着给别的工程用,还算靠谱的一个函数~