首页 > 解决方案 > 检查 iofstream 上是否有数据的非阻塞方式

问题描述

我需要一种方法来检查文件(fifo)上是否有数据以非阻塞方式读取。我试过使用peek;但它是阻塞的,我试图获取然后取消获取一个字符,以便在不更改内容的情况下检查文件;但再次get被阻止......

我发现的唯一非阻塞解决方案是使用std::getline(file, line_str)并检查字符串是否为空;但是,这不适合我的需要,因为它会更改文件上的数据。(数据是一个序列化的对象,一旦我检测到有东西要读取,我就会读取)。

注意:我需要它是非阻塞的:我有多个文件流,需要定期检查所有文件流,以查看是否有要读取/反序列化的对象。

这是我想要实现的一个简单示例:

发件人.cpp

#include <fstream>
#include <iostream>
#include <string>
extern "C"{
    #include <sys/stat.h>      // S_IRUSR, S_IWUSR, mkfifo
}
#include <cerrno>              // errno

int main(int, char** argv) {
    std::string pipe = "foobar";
    if(mkfifo(pipe.c_str(), S_IRUSR | S_IWUSR) < 0){
        if (errno != EEXIST){
            std::cerr << errno;
        }
    }
    std::ofstream file{pipe.c_str()};
    file.write("boop", 4); // Simulated object serialization

}

阅读器.cpp

#include <fstream>
#include <iostream>
#include <string>
extern "C"{
    #include <sys/stat.h>      // S_IRUSR, S_IWUSR, mkfifo
}
#include <cerrno>              // errno

int main(int, char** argv) {
    std::string pipe = "foobar";
    if(mkfifo(pipe.c_str(), S_IRUSR | S_IWUSR) < 0){
        if (errno != EEXIST){
            std::cerr << errno;
        }
    }
    std::ifstream file{pipe.c_str()};
    // ...
    /* Do check for data and read/deserialize if any data */
    // This is in some sort of loop that goes over the different
    // filestreams and checks to see if they have data to treat
}

任何帮助都非常感谢......

编辑:按照 Zoso 的回答,我尝试使用文件大小来确定文件是否已更改;但是尝试获取 fifo 命名管道的大小是不可能的: filesystem error: cannot get file size: Operation not supported [myFilePath]

标签: c++filenonblockingostream

解决方案


我不确定这是否适用于您的特定用例,但您可以使用filesystemAPI。一个简单的例子是

#include <iostream>
#include <fstream>
#include <filesystem>

namespace fs = std::filesystem;
int main()
{
    while (true) {
        auto path = fs::current_path().append("test");
        std::cout <<"Press enter to know file size of "<<path.c_str() <<'\n';
        char c= getchar();
        try {
            std::cout<<"Size of "<<path.c_str()<<"is "<<fs::file_size(path)<<'\n';
        } catch(fs::filesystem_error& e) {
            std::cout << e.what() << '\n';
        }        
    }
}

当文件获取数据时,可以根据数据的增加size对其进行跟踪,并且可以在使用该数据时跟踪要处理的数据。


推荐阅读