c++ - 检查 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]
解决方案
我不确定这是否适用于您的特定用例,但您可以使用filesystem
API。一个简单的例子是
#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
对其进行跟踪,并且可以在使用该数据时跟踪要处理的数据。