在98下COPY文件,用了四个方案:
1、用API CreateFile、ReadFile、WriteFile...
2、用API CopyFile(CopyFileEx不支持98)
3、用MFC CFile类
4、用Shell SHFileOperation所有的这些,对于几十兆的“大”文件我发现都会吃掉我的内存,程序退出也没有办法回收。我的初衷是要做一个象CopyFileEx功能一样的函数,这样我的程序原来只支持2000的在98下也一样可以运行!可是98搞出很多问题来,内存的大量消耗,资源无法获取,系统崩溃!
不知道为什么?好象以前98时代没有人写了个程序说很容易死的,我想一定是我的参数的问题!下面是我的部分代码,对于CreateFile的dwFlagsAndAttributes参数我用FILE_FLAG_WRITE_THROUGH是不会出问题,不过我的文件大小就没得变了!
呵呵,可能太长了没人看!

解决方案 »

  1.   

    HANDLE hFileSrc = ::CreateFile(lpExistingFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
    if (INVALID_HANDLE_VALUE != hFileSrc)
    {
    HANDLE hFileDst = ::CreateFile(lpNewFileName, GENERIC_WRITE, 
       0, NULL, CREATE_ALWAYS,
       ::GetFileAttributes(lpExistingFileName) | FILE_FLAG_NO_BUFFERING, NULL);
    if (INVALID_HANDLE_VALUE == hFileDst)
    {
    DWORD dwErr = GetLastError();
    ::CloseHandle (hFileSrc);
    SetLastError(dwErr);
    return FALSE;
    }
    BYTE *pBuffer = new BYTE[COPY_FILE_BUFFER_SIZE];
    DWORD dwReadByte = 0;
    DWORD dwWriteByte = 0;
    LARGE_INTEGER TotalFileSize;
    TotalFileSize.LowPart = fdSrc.nFileSizeLow;
    TotalFileSize.HighPart = fdSrc.nFileSizeHigh;
    LARGE_INTEGER TotalBytesTransferred;
    TotalBytesTransferred.QuadPart = 0;
    LARGE_INTEGER StreamSize;
    StreamSize.QuadPart = 1;
    LARGE_INTEGER StreamBytesTransferred;
    StreamBytesTransferred.QuadPart = 0;
    DWORD dwStreamNumber = 1;
    DWORD dwCallbackReason = -1;
    HANDLE hSourceFile = hFileSrc;
    HANDLE hDestinationFile = hFileDst;
    do
    {
    if (dwCallbackReason == CALLBACK_CHUNK_FINISHED)
    break;
    if (!::ReadFile(hFileSrc, pBuffer, COPY_FILE_BUFFER_SIZE, &dwReadByte, NULL))
    {
    DWORD dwErr = GetLastError();
    ::SetFilePointer(hFileDst, 0, NULL, FILE_BEGIN);
    ::SetEndOfFile(hFileDst);
    ::CloseHandle(hFileDst);
    ::DeleteFile(lpNewFileName);
    ::CloseHandle(hFileSrc);
    delete pBuffer;
    SetLastError(dwErr);
    return FALSE;
    }
    if (dwReadByte < COPY_FILE_BUFFER_SIZE)//finish
    {
    dwCallbackReason = CALLBACK_CHUNK_FINISHED;
    }
    TotalBytesTransferred.QuadPart += dwReadByte;
    if (!::WriteFile(hFileDst, pBuffer, COPY_FILE_BUFFER_SIZE, &dwWriteByte, NULL))
    {
    DWORD dwErr = GetLastError();
    ::SetFilePointer(hFileDst, 0, NULL, FILE_BEGIN);
    ::SetEndOfFile(hFileDst);
    ::CloseHandle(hFileDst);
    ::DeleteFile(lpNewFileName);
    ::CloseHandle(hFileSrc);
    delete pBuffer;
    SetLastError(dwErr);
    return FALSE;
    }
    if (COPY_FILE_BUFFER_SIZE != dwWriteByte)
    {
    ::SetFilePointer(hFileDst, 0, NULL, FILE_BEGIN);
    ::SetEndOfFile(hFileDst);
    ::CloseHandle(hFileDst);
    ::DeleteFile(lpNewFileName);
    ::CloseHandle(hFileSrc);
    delete pBuffer;
    return FALSE;
    } //::CloseHandle(hFileDst);
    //hFileDst = ::CreateFile(lpNewFileName, GENERIC_WRITE, 
    // 0, NULL, OPEN_EXISTING,
    // ::GetFileAttributes(lpExistingFileName), NULL);
    //::FlushFileBuffers(hFileDst);
    //::SetFilePointer(hFileDst, 0, NULL, FILE_END);
    }while(TRUE);

    ::SetFilePointer(hFileDst, TotalBytesTransferred.LowPart, NULL, FILE_BEGIN);
    ::SetEndOfFile(hFileDst);
    DWORD dwErr = GetLastError();
    ::CloseHandle(hFileDst);
    delete pBuffer;
    ::CloseHandle(hFileSrc);
    return TRUE;
    }
      

  2.   

    对于最后的几行:
    ::SetFilePointer(hFileDst, TotalBytesTransferred.LowPart, NULL, FILE_BEGIN);
    ::SetEndOfFile(hFileDst);
    如果用了FILE_FLAG_NO_BUFFERING SetEndOfFile会有错误(ERROR =5 访问拒绝),也就是说文件大小只能是扇区的倍数,那就太变态了!
    如果改成FILE_FLAG_WRITE_THROUGH,内存没有回收!我打算用C Runtime lib
    可是不知道行不行!
      

  3.   

    你char* pBuffer = new char [],再delete pBuffer,会回收内存才怪了呢
      

  4.   

    我没有看你的源码,只发表一下意见,应该不是内存问题,内存用完是常有的事,有虚拟内存的。所有的内存在程序结束后一定被回收。而且WIN2000与WIN98内存是一样多的,为什么WIN2000没事?是资源问题,因为WIN2000对资源是不加限制的,WIN98却不行。在WIN98下,我测试创建3000个EDIT,或在OnDraw中创建的pen等不释放,很快系统不行了,由于系统已崩溃,程序结束也不能回收。WIN2000下没问题。while(1)
    {
    double *p = new double[1000];//你内存泄漏不会严重至此吧?
    }三秒后内存耗尽,半小时后虚拟内存耗尽,提示无磁盘空间,退出程序,所有空间回收了。
      

  5.   

    hnyyy(前进) ( )
    你说得对,我也想过是这样的问题,我做了你这样的测试,系统回收了我分配的内存(在程序EXIT之后)不过我说的问题不是因为我的程序分配的内存,是WINDOWS在写文件的时候,你知道是写文件系统并不是马上就给你写到DISK上,可能要到一定的数据量的时候才会这样做,那么在内存里一定了一个BUFFER来让你写,这是系统在做的,应该CLOSE文件这些文件缓存都应该释放才对,可是我这里看不到这个释放。如果是我程序分配的内存当然我知道如何释放了!DoItFreely(Freely) ( )
    你说得对,不过不是这里的问题,我没有加[ ]可能会泄露,可是我在一次COPY里NEW 1M的内存,这样说来最多就一次1M了(不是一人循环是一个文件),我COPY一个300M的文件,等COPY完成我用兔子监测原来有200M的可用物理内存,慢慢少到只有1M,然后是交换内存开始少了,要是我不用它来整理一下我的系统很容易就死了,本来说来还有虚拟内存可以用,系统不可能崩溃,可是98就是这么脆弱!
      

  6.   

    再TO hnyyy(前进) ( ) 
    不要以为98和2000一样,我的程序就是在2000下开发的,一切都很好!
    老板说要对98也支持,于是就做了,可是出现的问题多多,老死机,查的好久才查出这个问题!
    你说的GDI资源的释放我也出过问题,是这样的,2000下GDI可以随便用,98下要是不注意释放就会吃苦头!
      

  7.   

    其实我现在是解决了这个问题,只不过是治标不治本而已:
    在文件COPY完后,因为大小是扇区的倍数,所以文件最后有一些是不要的,我再CREATEFILE一次裁去多余的尾巴
    hFileDst = ::CreateFile(lpNewFileName, GENERIC_WRITE, 
    FILE_SHARE_READ, NULL, CREATE_ALWAYS,
    ::GetFileAttributes(lpExistingFileName), NULL);
    if (INVALID_HANDLE_VALUE == hFileDst)
    {
    return FALSE;
    }
    else
    {
    ::SetFilePointer(hFileDst, TotalBytesTransferred.LowPart, NULL, FILE_BEGIN);
    ::SetEndOfFile(hFileDst);
    ::CloseHandle(hFileDst);
    }因为其它地方还有很多文件读写有的用了CFile所以改起来很不爽,加上这是没有道理的事,为什么用MFC和API都这样,我想一定是有个地方有问题!