如何复制文件但触摸新副本上的时间戳?
Posted
技术标签:
【中文标题】如何复制文件但触摸新副本上的时间戳?【英文标题】:How to copy a file but touch the timestamp on the new copy? 【发布时间】:2014-10-22 18:11:34 【问题描述】:我正在使用::CopyFile()
来制作文件的副本。看来原始文件的时间戳正在被保留,我希望副本在副本上设置当前时间戳,即“触摸”它。
有没有一种 WinAPI 方法可以轻松做到这一点?
【问题讨论】:
谷歌搜索winapi set file time 有一些可能性。 【参考方案1】:如果您阅读MSDN documentation 中的CopyFile()
,底部的 cmets 会说以下内容:
文件时间语义 本文应记录有关文件创建/修改/访问时间的语义。
创建时间:如果目标文件已经存在,则保留其创建时间,否则设置为当前系统时间。 上次修改时间:始终从源文件的修改时间复制。 上次访问时间:始终设置为当前系统时间。
和
修改时间并不总是保留 不保证设置修改时间。 CopyFileEx 确实会尝试设置修改时间,但不会对其进行错误检查。这意味着如果在 CopyFileEx 内部设置修改时间失败(例如访问被拒绝),后者仍然会返回成功!
因此,如果修改时间对您的方案很重要(它适用于我的同步程序),您必须显式调用 SetFileTime() 并检查它的返回值以确定。
您应该使用SetFileTime()
自行更新复制文件的时间戳,以确保将它们设置为您希望它们设置的值。 MSDN上有一个例子:
Changing a File Time to the Current Time
#include <windows.h>
// SetFileToCurrentTime - sets last write time to current system time
// Return value - TRUE if successful, FALSE otherwise
// hFile - must be a valid file handle
BOOL SetFileToCurrentTime(HANDLE hFile)
FILETIME ft;
SYSTEMTIME st;
BOOL f;
GetSystemTime(&st); // Gets the current system time
SystemTimeToFileTime(&st, &ft); // Converts the current system time to file time format
f = SetFileTime(hFile, // Sets last-write time of the file
(LPFILETIME) NULL, // to the converted current system time
(LPFILETIME) NULL,
&ft);
return f;
【讨论】:
【参考方案2】:::CopyFile 实际上是 windows 的一部分:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363851%28v=vs.85%29.aspx
这是一个复制元数据的便利功能。还有另一种使用 Windows 复制文件的方法,虽然不太方便。看看这些函数:
读取文件: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx
创建文件: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
写入文件: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx
HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
BOOL WINAPI ReadFile(
_In_ HANDLE hFile,
_Out_ LPVOID lpBuffer,
_In_ DWORD nNumberOfBytesToRead,
_Out_opt_ LPDWORD lpNumberOfBytesRead,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
所以你可以这样打开文件:
CreateFile(<File>, GENERIC_READ, FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)
检查无效的返回句柄,
使用以下内容创建新文件:
CreateFile(<File>, GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)
检查无效的返回句柄,
将文件读入缓冲区:
ReadFile(handle for file 1, buffer, Buffer size, Destination file,OUT for Bytes Read, NULL)
然后写出Buffer:
WriteFile(outfile handle,buffer,number of bytes,NULL)
合上你的把手。
请务必阅读 CreateFiles 详细信息,它也可用于打开文件。
【讨论】:
以上是关于如何复制文件但触摸新副本上的时间戳?的主要内容,如果未能解决你的问题,请参考以下文章