c++

c++遍历文件能实时更新吗

小樊
84
2024-12-06 04:28:06
栏目: 编程语言

在C++中,遍历文件并实时更新通常意味着在读取文件内容的同时,能够检测到文件的更改并相应地更新输出。这可以通过多种方式实现,具体取决于你的需求和使用的操作系统。

以下是一些常见的方法:

1. 使用 std::filesystem 库(C++17及以上)

std::filesystem 库提供了方便的接口来遍历文件和目录。你可以结合使用 std::filesystem::directory_iteratorstd::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;
}

2. 使用操作系统特定的API

Windows

在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

在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。请注意,长时间运行的程序可能会消耗大量系统资源,因此请确保在实际应用中进行适当的优化和资源管理。

0
看了该问题的人还看了