【发布时间】:2021-02-14 06:49:24
【问题描述】:
首先让我说我在 C++ 中大约 3 天大。
好的,主要问题,我有一个跨越多行的文件,我试图重复打印一个特定的行,这可能会被其他进程任意更改。
示例文件:
line0
line1
somevar: someval
line3
line4
我正在尝试打印中间行(以somevar 开头的行)。我的第一次天真尝试是打开文件,循环浏览内容并打印确切的行,然后移动到文件的开头。
#include <iostream>
#include <fstream>
#include <string>
int main (int argc, char *argv[])
{
std::string file = "input.txt";
std::ifstream io {file};
if (!io){
std::cerr << "Error opening file" <<std::endl;
return EXIT_FAILURE;
}
std::string line;
std::size_t pos;
while (getline (io, line))
{
pos = line.find_first_of(' ');
if (line.substr (0, pos) == "somevar:")
{
// someval is expected to be an integer
std::cout << std::stoi( line.substr (pos) ) ) << std::endl;
io.seekg (0, std::ios::beg);
}
}
io.close();
return EXIT_SUCCESS;
}
结果:只要文件更新,程序就会退出。
我开始认为我正在执行的 IO 实际上是缓冲的,因此更新文件不应该像那样反映在我们现有的缓冲区中(这不是 shell 脚本)。所以现在我想让我们在每次迭代时打开和关闭文件,这应该每次都有效地刷新缓冲区,我知道不是最好的解决方案,但我想测试一下理论。这是新的来源:
#include <iostream>
#include <fstream>
#include <string>
int main (int argc, char *argv[])
{
std::string proc_file = "input.txt";
std::ifstream io;
if (!io){
std::cerr << "Error opening file" <<std::endl;
return EXIT_FAILURE;
}
std::string line;
std::size_t pos;
while (io.open(proc_file, std::ios::in), io)
{
io.sync();
getline (io, line);
pos = line.find_first_of(' ');
// The line starting with "somevar:" is always going to be there.
if (line.substr (0, pos) == "somevar:")
{
std::cout << std::stoi( line.substr (pos) ) ) << std::endl;
io.close();
}
}
io.close();
return EXIT_SUCCESS;
}
结果:和以前一样。
实现我的目标的理想方式是什么?另外,为什么每当有问题的文件被更新时程序就会退出?谢谢(:
编辑:我要读取的文件是"/proc/" + std::to_string( getpid() ) + "/io",该行是读取的字节之一(以read_bytes: 开头)。
【问题讨论】:
-
缓冲也可能发生在写入端——即文件的实际内容(在文件系统的缓存和硬盘驱动器本身)在写入程序运行之前不能保证更新缓冲区被刷新和/或关闭其文件句柄。您是否有机会修改编写程序以使用其他机制(例如 TCP 套接字、管道或内存映射文件)?尝试使用文件作为进程间通信机制是相当不确定的。
-
似乎是使用sqlite 的好案例。 您的问题是特定于操作系统的。如果在 Linux 上,请使用
Linux标记您的问题。在这种情况下,请阅读 inode(7) 和 inotify(7) -
我的感觉是你需要几个星期的全职工作。也许与提供更改文件的合作伙伴/客户讨论可能是值得的。否则,我建议直接使用 syscalls(2) 并避免使用 C++ 流。在 Linux 上,行只是与文件中的
\n(换行符)字符相关的约定!