读取不断更新的文件 (C++)
Read a file that's constantly updated (C++)
首先让我说我在 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:
开头)。
The file I'm trying to read is some /proc/1234/io
这是最重要的信息。
proc(5) are small pseudo-files (a bit like pipe(7)-s) 中的文件,只能按顺序读取。
那个伪文件没有更新,而是完全重新生成(由 Linux kernel whose source code you can study) at every open(2)
因此,您只需快速读取内存中的所有文件,并在读取后处理内存中的内容。
参见 this answer 一个非常相关的问题....使其适应 C++
正如在评论中发现的那样,您不是在读取磁盘上的“真实”文件,而是 /proc/PID/io
这是一个虚拟文件,其内容只有在打开时才能确定,这要归功于 VFS。您关于它可以“通过其他进程任意更改”的说法具有误导性,该文件永远不会更改,只是每次打开时内容都不同。
所以现在我们知道再多的寻求也无济于事。每次我们想要阅读它时,我们只需要重新打开文件。这可以相当简单地完成:
char content[1000]; // choose a suitable value
const char key[] = "read_bytes:";
while (true)
{
std::ifstream io(io_filename);
if (!io.read(content, sizeof(content)))
break;
auto it = std::search(content, std::end(content), key, key + strlen(key));
std::cout << atoi(it + strlen(key)) << std::endl;
}
你应该做一些比 atoi()
更小心的事情,它不会在数组的末尾停止,但我假设你的真实应用程序会在那里做其他事情,所以我省略了处理。
首先让我说我在 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:
开头)。
The file I'm trying to read is some
/proc/1234/io
这是最重要的信息。
proc(5) are small pseudo-files (a bit like pipe(7)-s) 中的文件,只能按顺序读取。
那个伪文件没有更新,而是完全重新生成(由 Linux kernel whose source code you can study) at every open(2)
因此,您只需快速读取内存中的所有文件,并在读取后处理内存中的内容。
参见 this answer 一个非常相关的问题....使其适应 C++
正如在评论中发现的那样,您不是在读取磁盘上的“真实”文件,而是 /proc/PID/io
这是一个虚拟文件,其内容只有在打开时才能确定,这要归功于 VFS。您关于它可以“通过其他进程任意更改”的说法具有误导性,该文件永远不会更改,只是每次打开时内容都不同。
所以现在我们知道再多的寻求也无济于事。每次我们想要阅读它时,我们只需要重新打开文件。这可以相当简单地完成:
char content[1000]; // choose a suitable value
const char key[] = "read_bytes:";
while (true)
{
std::ifstream io(io_filename);
if (!io.read(content, sizeof(content)))
break;
auto it = std::search(content, std::end(content), key, key + strlen(key));
std::cout << atoi(it + strlen(key)) << std::endl;
}
你应该做一些比 atoi()
更小心的事情,它不会在数组的末尾停止,但我假设你的真实应用程序会在那里做其他事情,所以我省略了处理。