在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、用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是不会出问题,不过我的文件大小就没得变了!
呵呵,可能太长了没人看!
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;
}
::SetFilePointer(hFileDst, TotalBytesTransferred.LowPart, NULL, FILE_BEGIN);
::SetEndOfFile(hFileDst);
如果用了FILE_FLAG_NO_BUFFERING SetEndOfFile会有错误(ERROR =5 访问拒绝),也就是说文件大小只能是扇区的倍数,那就太变态了!
如果改成FILE_FLAG_WRITE_THROUGH,内存没有回收!我打算用C Runtime lib
可是不知道行不行!
{
double *p = new double[1000];//你内存泄漏不会严重至此吧?
}三秒后内存耗尽,半小时后虚拟内存耗尽,提示无磁盘空间,退出程序,所有空间回收了。
你说得对,我也想过是这样的问题,我做了你这样的测试,系统回收了我分配的内存(在程序EXIT之后)不过我说的问题不是因为我的程序分配的内存,是WINDOWS在写文件的时候,你知道是写文件系统并不是马上就给你写到DISK上,可能要到一定的数据量的时候才会这样做,那么在内存里一定了一个BUFFER来让你写,这是系统在做的,应该CLOSE文件这些文件缓存都应该释放才对,可是我这里看不到这个释放。如果是我程序分配的内存当然我知道如何释放了!DoItFreely(Freely) ( )
你说得对,不过不是这里的问题,我没有加[ ]可能会泄露,可是我在一次COPY里NEW 1M的内存,这样说来最多就一次1M了(不是一人循环是一个文件),我COPY一个300M的文件,等COPY完成我用兔子监测原来有200M的可用物理内存,慢慢少到只有1M,然后是交换内存开始少了,要是我不用它来整理一下我的系统很容易就死了,本来说来还有虚拟内存可以用,系统不可能崩溃,可是98就是这么脆弱!
不要以为98和2000一样,我的程序就是在2000下开发的,一切都很好!
老板说要对98也支持,于是就做了,可是出现的问题多多,老死机,查的好久才查出这个问题!
你说的GDI资源的释放我也出过问题,是这样的,2000下GDI可以随便用,98下要是不注意释放就会吃苦头!
在文件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都这样,我想一定是有个地方有问题!