即使返回成功,数据也不能写入流中
问题描述:
我正在编写一个程序,它使用libcurl获取大量电子邮件文件,然后将文件写入磁盘,然后生成收据。即使返回成功,数据也不能写入流中
我的问题是,尽管大部分收据似乎都被写入,但大部分电子邮件并未写入磁盘。更糟糕的是,即使文件没有写入,ofstream也会返回成功 - 所以即使写入文件没有成功完成,也会写入收据。
我的猜测是,因为流是异步的,如果一个写入没有及时完成,那么它将被放置在地板上 - 只有一定数量的写入可以同时进行。我只是在这里猜测。 也许我需要重构我的代码来同步编写 - 但我不能相信这是必要的。有没有人有任何想法我可以做这项工作?
电子邮件的大小范围从几个千字节到几个兆字节。
int write_file(string filename, string mail_item) {
ofstream out(filename.c_str());
out << mail_item;
out.close();
out.flush();
if (!out) {
return FUNCTION_FAILED;
}
return FUNCTION_SUCCESS;
}
这是另一种功能的一部分,并且已经被切出,从而只显示了这一问题的突出代码。
vector<string> directory = curl_listroot(curl);
for (int i=0; i<directory.size(); i++) {
vector<int> mail_list = curl_search(curl,directory[i],make_vector<string>() << "SEEN" << "RECENT" << "NEW" << "ANSWERED" << "FLAGGED");
for (int j=0; j<mail_list.size(); j++) {
curl_reset(curl, imap.username, imap.password);
string mail_item = curl_fetch(curl,directory[i],mail_list[j]);
if (mail_item.compare("") != 0) {
string m_id = getMessageID(mail_item);
string filename = save_path+"/"+RECEIPTNAME+"/"+clean_filename(m_id) + ".eml";
if (!file_exists(filename)) {
string real_filename;
real_filename = save_path+"/"+INBOXNAME+"/"+clean_filename(m_id) + ".eml";
int success = write_file(real_filename, mail_item);
if (success == FUNCTION_SUCCESS) {
write_file(filename, ""); //write empty receipt
}
}
}
}
}
所有建议感激地收到!谢谢!
答
好的。我找到了答案 - 可能会有更好的答案 - 但这个对我来说很有用。问题似乎出现在操作系统(在这种情况下为Linux) - 流完成后,将文件写入操作系统的责任交给了操作系统,但文件还没有真正写入(所以虽然流可能同步结束结束写入文件,从数据到安全写入磁盘的文件,不是)。鉴于我正在快速连续(可能有成千上万)的大量写入,这不一定会奏效。操作系统可能会把手放在空中,并在地板上放置大量的文件写入(因此我最初的请求是同步写入文件的方式 - 端到端)。
我的解决方案是在每次写入后暂停以使操作系统时间赶上。它虽然不雅,但并不像应该的那么高效 - 写一个空文件并不需要半秒。另外,在慢速存储上,半秒时间可能不够。我会欢迎任何有关如何改进我的代码的巧妙建议。
int write_file(string filename, string mail_item) {
ofstream out(filename.c_str());
if (!out) {
return FUNCTION_FAILED;
}
out << mail_item << endl;
out.flush();
usleep(500000); //wait for half a second to give the OS time to output the file
if (!out) {
return FUNCTION_FAILED;
}
out.close();
if (!out) {
return FUNCTION_FAILED;
}
return FUNCTION_SUCCESS;
}
尝试在打开流后检查流的状态。你写完之后。关闭后。您不需要在刷新后执行它,因为您不需要刷新(作为关闭的一部分,流缓冲区将被刷新)。 –
有些东西与你粘贴的代码不正确。'int write_file(string filename,string mail_item){'是一个函数声明,并且在它是'for'循环之后。 –
为什么不在'out user0042