在C+中读取行后删除行+;使用系统()的程序 我试图理解C++中的文件I/O如何在C++或C中处理。我的目标是逐行读取文件,并将这些行发送到远程服务器。如果发送了该行,我想将其从文件中删除 我尝试的一种方法是保持读取的行数,并调用system()system调用来删除“count”行数。我使用了bash命令:sed-I-e1,'count'd filename 之后,我继续阅读该文件,令人惊讶的是,它按计划工作。 我有两个问题: 这样可靠吗 为什么这一切都有效呢 阅读文件时,我删除了其中的一部分,但它仍然有效?如果我 a是否寻求以前的职位,然后呢
最好的,迪格维杰 附言:在C+中读取行后删除行+;使用系统()的程序 我试图理解C++中的文件I/O如何在C++或C中处理。我的目标是逐行读取文件,并将这些行发送到远程服务器。如果发送了该行,我想将其从文件中删除 我尝试的一种方法是保持读取的行数,并调用system()system调用来删除“count”行数。我使用了bash命令:sed-I-e1,'count'd filename 之后,我继续阅读该文件,令人惊讶的是,它按计划工作。 我有两个问题: 这样可靠吗 为什么这一切都有效呢 阅读文件时,我删除了其中的一部分,但它仍然有效?如果我 a是否寻求以前的职位,然后呢,c++,bash,sed,C++,Bash,Sed,最好的,迪格维杰 附言: 如果有人能提出更好的办法,我会很高兴的 下面是我编写的程序的代码: #include<iostream> #include<fstream> #include<string> #include<sstream> #include<cstdlib> int main(){ std::ifstream f; std::string line; std::stringstream ss;
如果有人能提出更好的办法,我会很高兴的 下面是我编写的程序的代码:
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<cstdlib>
int main(){
std::ifstream f;
std::string line;
std::stringstream ss;
int i=0;
f.open("in.txt");
if(f.is_open()){
while(getline(f,line)){
std::cout<<line<<std::endl;
i++;
if(i==2)break;
}
ss<<"sed -i -e 1,"<<i<<"d in.txt";
system(ss.str().c_str());
while(getline(f,line)){
std::cout<<line<<std::endl;
}
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
int main(){
std::iff流;
std::字符串行;
std::stringstream-ss;
int i=0;
f、 打开(“in.txt”);
如果(f.是开着的()){
while(getline(f,line)){
std::cout首先,尽可能避免使用系统
调用(如果可能,根本不要使用),因为它们会造成竞争条件和其他问题,这些问题非常严重(而且经常发生)。如果涉及到文件访问,尤其如此
考虑到您的问题,有很多方法可以做到这一点,每种方法都有自己的注意事项
我将介绍三种可能的解决方案:
1) 如果文件足够小:
您可以在数据结构(向量、列表、deque等)中读取整个内容
删除原始文件
确定要读取的行数(并通过服务器协议发送)
然后将剩余的行作为原始文件的名称写入
如果以后打算并行化程序,如果文件较小,这可能是一个更好的解决方案。注意:较小是一个相对术语,但通常受可用内存的限制
2) 如果文件相当大或受内存限制,则必须使用缓冲区进行创作。一旦读取了一行并通过程序成功发送,则可以确定文件指针的位置,并将剩余信息作为新文件复制到当前文件的结尾。完成后,关闭并删除该文件旧文件,然后关闭新文件并将其重命名为与旧文件相同的名称
< P > 3)如果你的解决方案不必在C++中,你可以使用shell脚本或(有争议的)另一种语言来完成任务。 < P > 1)不,不可靠。
2)C++运行库在块中(内部)读取文件,然后将其分为(高级)输入请求,直到块被耗尽,强制(内部)从磁盘读取更多块。由于在调用
sed
之前读取了一个或多个物理块,因此,如果sed
碰巧更改了文件的第一部分,则无法对其进行更改
若要查看代码失败,您需要将输入文件设置为足够大,以便在调用sed
“fail”之前(运行库内部)仍有未读入的文件块我的意思是,在sed
删除一些行之前,您的程序不会看到文件中原来的所有字符。sed编写文件的新版本,而程序一直读取它打开的同一版本。这是Unix和Linux的常见行为,当一个程序编写另一个程序打开的文件时。>
您可以通过这个小C程序自己看到这一点:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
FILE *f = fopen("in.txt", "r");
while (1) {
rewind(f);
int lines = 0;
int c;
while ((c = getc(f)) != EOF)
if (c == '\n')
++lines;
printf("Number of lines in file: %d\n", lines);
}
return 0;
}
#包括
#包括
内部主(空){
文件*f=fopen(“in.txt”,“r”);
而(1){
倒带(f);
int行=0;
INTC;
而((c=getc(f))!=EOF)
如果(c=='\n')
++线条;
printf(“文件中的行数:%d\n”,行);
}
返回0;
}
在一个窗口中运行该程序,然后在另一个窗口中使用sed编辑该文件。即使磁盘上的文件已被编辑,该程序打印的行数也将保持不变,这是因为Unix保留旧的开放版本,即使其他程序无法再访问它
关于你的第一个问题,你的解决方案是多么的可靠,据我看,它应该是可靠的,除了通常的警告系统崩溃或在更新过程中内存用完,其他人访问文件,当然还有“强”系统< /强>调用的所有问题。对于大型数据集,您可能希望采用不同的方式
sujin关于为要保留的行使用临时文件的评论似乎是合理的。这将更快更安全。保留原始文件,这样如果系统崩溃,您仍然可以保留数据,并等待完成将旧文件重命名为“in.txt.bak”,然后将临时文件重命名为“in.txt”.正如其他人所说,在读取原始文件后,您必须使用所需的记录创建另一个文件,然后将其删除。但是在这个应用程序中,您可能会看到fifo比文件更有用。如果您在*NIX平台上,请从控制台检查makefifo语句
这就像一个具有奇异性的文件,在读取一行之后,它会被删除。大多数现代文件系统不支持删除文件开头的行,因此这样做会非常低效
解决实际问题的正常方法是在日志文件达到一定大小时停止写入,然后开始写入新文件。一旦写入整个文件,复制这些文件的代码就可以删除整个文件(这是一种有效的操作)。创建另一个临时文件并复制您需要的行