在C++中,遍历文件并实时更新通常意味着在读取文件内容的同时,能够检测到文件的更改并相应地更新输出。这可以通过多种方式实现,具体取决于你的需求和使用的操作系统。
以下是一些常见的方法:
std::filesystem
库(C++17及以上)std::filesystem
库提供了方便的接口来遍历文件和目录。你可以结合使用 std::filesystem::directory_iterator
和 std::filesystem::path
来遍历文件,并使用 std::filesystem::last_write_time
来检查文件的最后修改时间。
#include <iostream>
#include <filesystem>
#include <chrono>
namespace fs = std::filesystem;
void watch_file(const fs::path& path) {
while (true) {
auto now = std::chrono::system_clock::now();
auto last_write_time = fs::last_write_time(path);
auto duration = std::chrono::duration_cast<std::chrono::seconds>(now - last_write_time).count();
if (duration > 1) { // 每秒检查一次
std::cout << "File updated: " << path << std::endl;
// 这里可以添加读取文件内容的代码
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
fs::path path = "path/to/your/file.txt";
watch_file(path);
return 0;
}
在Windows上,可以使用 ReadDirectoryChangesW
函数来监视目录的变化。
#include <iostream>
#include <windows.h>
void watch_file(const std::wstring& path) {
HANDLE hDir = CreateFileW(
path.c_str(),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
std::cerr << "Error opening directory: " << GetLastError() << std::endl;
return;
}
BYTE buffer[1024];
DWORD bytesReturned;
OVERLAPPED overlapped = { 0 };
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while (true) {
if (ReadDirectoryChangesW(
hDir,
buffer,
sizeof(buffer),
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION,
&bytesReturned,
&overlapped,
NULL)) {
DWORD bytesTransferred;
if (GetOverlappedResult(hDir, &overlapped, &bytesTransferred, TRUE)) {
FILE_NOTIFY_INFORMATION* pNotifyInfo = (FILE_NOTIFY_INFORMATION*)buffer;
do {
std::wstring fileName(pNotifyInfo->FileName, pNotifyInfo->FileNameLength / sizeof(wchar_t));
if (fileName != L"." && fileName != L"..") {
std::wcout << L"File updated: " << fileName << std::endl;
// 这里可以添加读取文件内容的代码
}
pNotifyInfo = (FILE_NOTIFY_INFORMATION*)((BYTE*)pNotifyInfo + pNotifyInfo->NextEntryOffset);
} while (pNotifyInfo->NextEntryOffset != 0);
}
}
Sleep(1000); // 每秒检查一次
}
CloseHandle(hDir);
CloseHandle(overlapped.hEvent);
}
int main() {
std::wstring path = L"path\\to\\your\\file.txt";
watch_file(path);
return 0;
}
在Linux上,可以使用 inotify
API来监视文件系统的变化。
#include <iostream>
#include <sys/inotify.h>
#include <unistd.h>
#include <cstring>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
void watch_file(const std::string& path) {
int length, i = 0;
int fd = inotify_init();
if (fd < 0) {
std::cerr << "inotify_init error" << std::endl;
return;
}
int wd = inotify_add_watch(fd, path.c_str(), IN_MODIFY);
if (wd < 0) {
std::cerr << "inotify_add_watch error" << std::endl;
close(fd);
return;
}
char buffer[BUF_LEN];
while (true) {
length = read(fd, buffer, BUF_LEN);
if (length < 0) {
std::cerr << "read error" << std::endl;
break;
}
while (i < length) {
struct inotify_event* event = (struct inotify_event*)&buffer[i];
if (event->len) {
if (event->mask & IN_MODIFY) {
std::cout << "File updated: " << path << std::endl;
// 这里可以添加读取文件内容的代码
}
}
i += EVENT_SIZE + event->len;
}
i = 0;
}
inotify_rm_watch(fd, wd);
close(fd);
}
int main() {
std::string path = "path/to/your/file.txt";
watch_file(path);
return 0;
}
以上方法展示了如何在C++中实时监控文件的更改。你可以根据自己的需求选择合适的方法,并根据操作系统选择相应的API。请注意,长时间运行的程序可能会消耗大量系统资源,因此请确保在实际应用中进行适当的优化和资源管理。