我有一个适用于Windows 7的Visual Studio 2008 C ++应用程序,我想在其中查看文件以进行更改。
文件可能会改变如下:
std::ofstream myfile_;
void LogData( const char* data )
{
myfile_ << data << std::endl;
// note that the file output buffer is flushed by std::endl, but the file is not closed.
}
我尝试使用带有FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME
标志的ReadDirectoryChangesW和FindFirstChangeNotification来查看文件的目录。但是,在文件句柄实际关闭之前,这些API都不会检测文件更改。
有没有办法在实际写入文件时检测到更改,但是在文件句柄关闭之前?
谢谢, PaulH
更新 在@ Edwin的建议下,我正在尝试使用Journal功能。但是,我有几个问题。
FSCTL_READ_USN_JOURNAL
给我的东西?为简洁起见,省略了错误检查。
boost::shared_ptr< void > directory(
::CreateFileW( L"C:\\Foo\\Bar\\Myfile.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL ),
::CloseHandle );
USN_JOURNAL_DATA journal = { 0 };
DWORD returned = 0;
::DeviceIoControl( directory.get(), FSCTL_QUERY_USN_JOURNAL, NULL, 0, &journal, sizeof( journal ), &returned, NULL );
BYTE buffer[ 4096 ] = { 0 };
READ_USN_JOURNAL_DATA read = { 0, USN_REASON_DATA_EXTEND | USN_REASON_DATA_TRUNCATION, FALSE, 0, 0, journal.UsnJournalID };
::DeviceIoControl( directory.get(), FSCTL_READ_USN_JOURNAL, &read, sizeof( read ), &buffer, sizeof( buffer ), &returned, NULL );
for( USN_RECORD* record = ( USN_RECORD* )( buffer + sizeof( USN ) );
( ( BYTE* )record - buffer ) < returned;
record = ( USN_RECORD* )( ( BYTE* )record + record->RecordLength ) )
{
ATLTRACE( L"%s\r\n", record->FileName );
}
示例输出(这些都不在C:\ Foo \ Bar目录中):
AeXProcessList.txt`
AeXProcessList.txt`
AeXAMInventory.txt`
AeXAMInventory.txt`
AeXProcessList.txt`
AeXProcessList.txtP
access.log`
mysqlgeneral.log
E804.tmp
apache_error.log
E804.tmp
CHROME.EXE-5FE9909D.pfh
CHROME.EXE-5FE9909D.pfp
SyncData.sqlite3-journal
CHROME.EXE-5FE9909D.pfh
CHROME.EXE-5FE9909D.pfP
1211.tmp
SyncData.sqlite3-journal
AeXAMInventory.txt
答案 0 :(得分:2)
您可以使用
更改日记帐操作
(参见MSDN文档)
这是检测文件系统中任何变化的唯一100%保证方式。 但这很复杂。
答案 1 :(得分:1)
要读取特定文件或目录的数据,我相信您要使用FSCTL_READ_FILE_USN_DATA
而不是FSCTL_READ_USN_JOURNAL
。我相信后者总是检索整个卷的数据。但是,这不会填写您获得的USN记录的TimeStamp
,Reason
或SourceInfo
字段。如果您需要这些,我相信您可以使用FSCTL_READ_USN_JOURNAL
阅读它们,并指定您想要阅读的确切USN。
答案 2 :(得分:0)
不,因为在关闭文件句柄之前,无法保证操作系统只能写入一个字节。
异常可能是通过调用文件句柄上的flush
然后调用Windows API函数FlushFileBuffers
,但除非写入文件的程序执行此操作,否则不会写入任何字节。
答案 3 :(得分:0)
这可以通过监视FASTIO_WRITE和IRP_MJ_WRITE操作的过滤器驱动程序来完成。 Here是一篇非常好的指导文章。