0%

File operate2

CopyFileEx文件拷贝

一开始想用CopyFile,后来看到了这个,那就快用这个吧,还支持回调函数,看一下MSDN的一个定义:

1
2
3
4
5
6
7
8
9
10
11
BOOL CopyFileEx(
LPCWSTR lpExistingFileName,
// pointer to name of an existing file
LPCWSTR lpNewFileName,
// pointer to filename to copy to
LPPROGRESS_ROUTINE lpProgressRoutine,
// pointer to the callback function
LPVOID lpData, // to be passed to the callback function
LPBOOL pbCancel, // flag that can be used to cancel the operation
DWORD dwCopyFlags // flags that specify how the file is copied
);

前两个还是比较简单的,第三个参数是一个回调函数,定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER TotalFileSize, // total file size, in bytes
LARGE_INTEGER TotalBytesTransferred,
// total number of bytes transferred
LARGE_INTEGER StreamSize, // total number of bytes for this stream
LARGE_INTEGER StreamBytesTransferred,
// total number of bytes transferred for
// this stream
DWORD dwStreamNumber, // the current stream
DWORD dwCallbackReason, // reason for callback
HANDLE hSourceFile, // handle to the source file
HANDLE hDestinationFile, // handle to the destination file
LPVOID lpData // passed by CopyFileEx
);

第四个参数是要传递给回调函数的一个参数,可以为NULL,
第五个参数有点意思,就是为了防止文件过大,给了个可以强制结束的一个指针,BOOL类型的,如歌这个指针为TRUE的时候则会终止。
第六个参数是一个复制的类型,可以是下面这两个值:

Value Meaning
COPY_FILE_FAIL_IF_EXISTS The copy operation fails immediately if the target file already exists.
COPY_FILE_RESTARTABLE Progress of the copy is tracked in the target file in case the copy fails. The failed copy can be restarted at a later time by specifying the same values for lpExistingFileName and lpNewFileName as those used in the call that failed.
看名字就明白了,失败退出,失败重新。
那我们就试一下怎么个回事。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <windows.h>
using namespace std;
DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER TotalFileSize, // total file size, in bytes
LARGE_INTEGER TotalBytesTransferred,
// total number of bytes transferred
LARGE_INTEGER StreamSize, // total number of bytes for this stream
LARGE_INTEGER StreamBytesTransferred,
// total number of bytes transferred for
// this stream
DWORD dwStreamNumber, // the current stream
DWORD dwCallbackReason, // reason for callback
HANDLE hSourceFile, // handle to the source file
HANDLE hDestinationFile, // handle to the destination file
LPVOID lpData // passed by CopyFileEx
)
{
printf("%d\n",TotalBytesTransferred.u.LowPart);
return PROGRESS_CONTINUE;
}
int main()
{
CopyFileEx("1.zip","1\\3.zip",CopyProgressRoutine,NULL,NULL,COPY_FILE_RESTARTABLE);
}
看了下,主要就是那个回调函数的返回值比较重要一些,要继续的话呢要返回一个PROGRESS_CONTINUE这个值,其他的都不是太重要,仔细看看参数就好了。
## 删除文件DeleteFile
这个基本不用说,看下定义就知道了,就一个参数,删除的文件路径。
1
2
BOOL DeleteFile(  LPCTSTR lpFileName   // pointer to name of file to delete
);
但是在这里我还是要说一些比较关键的一些内容,删除不存在的文件的时候是会失败的,如果删除的文件是一个只读的属性,那么将会返回:ERROR_ACCESS_DENIED这个样子的一个值,这里我们写一个递归的函数(使用MFC的框架)实现递归删除。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void CStudy_HistoryDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString Context ;EContext.GetWindowTextA(Context);
RecursiveDelete(Context);
}


void CStudy_HistoryDlg::RecursiveDelete(CString szPath)
{
CFileFind ff;
CString strPath = szPath;
if ("\\" != strPath.Right(1))
{
strPath += "\\";
}
strPath += "*.*";//这个过滤器类型的东西貌似都是支持正则的。
BOOL bRet;//用来标记是不是已经删除完毕。
if (ff.FindFile(strPath))//这个应该就是文件夹的第一个指针开始。
{
do
{
bRet = ff.FindNextFile();//将内部的那个指针往下移动一下
if (ff.IsDots())//为.或..这种的上级目录
continue;
strPath = ff.GetFilePath();
if (!ff.IsDirectory())//看看是不是一个目录
{
//是一个文件
//删除文件
::SetFileAttributes(strPath,FILE_ATTRIBUTE_NORMAL);//先设置一下这个文件的属性,不要只读!!!
::DeleteFile(strPath);

}else
{
RecursiveDelete(strPath);//经典的递归调用
::SetFileAttributes(strPath,FILE_ATTRIBUTE_NORMAL);//和上面一样
::RemoveDirectory(strPath); //移除掉这个文件夹
}
} while (bRet);

}

}
我都做了一定的注释,就是一个递归删除,使用了MFC的一个框架,说实话微软给的这个框架是真的好!
需要注意,我们使用DeleteFile这个函数的话呢,是不会进入回收站的!

移动文件MoveFileEx

这次还是在用个Ex加强版本的吧,看一下Ex版本的MSDN定义:

1
2
3
4
5
BOOL MoveFileEx(
LPCTSTR lpExistingFileName, // pointer to the name of the existing file
LPCTSTR lpNewFileName, // pointer to the new name for the file
DWORD dwFlags // flag that specifies how to move file
);

第三个的参数有点古怪:
比较有意思的一个值:“MOVEFILE_DELAY_UNTIL_REBOOT”,这个值的意思就是说重启才会移动,具体怎么用我也没有去深入研究,没啥意思我感觉,而且与其他的不能同时使用。
MOVEFILE_COPY_ALLOWED:这个就是说可以移动到别的盘符,还有就是好像指定了这个就是类似于先Copy再删除这个样子的操作。
MOVEFILE_REPLACE_EXISTING:替换掉存在的。
MOVEFILE_WRITE_THROUGH:这个就是说等待函数结束才会返回。
说了这么多就实验一下吧。

1
2
3
4
5
6
7
8
#include <iostream>
#include <windows.h>
using namespace std;

int main()
{
MoveFileEx("1.txt","2.txt",MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH);
}

好吧也没啥可以验证的…