数据不是用 ofstream 写入的,即使返回成功也是如此



我正在编写一个程序,该程序使用 libcurl 获取大量电子邮件文件,然后将文件写入磁盘,然后生成收据。

我的问题是,虽然大多数收据似乎都被写好了,但大多数电子邮件都没有写到磁盘上。 更糟糕的是,即使文件没有被写入,ofstream 也会返回成功 - 因此即使文件写入没有成功完成,收据也会被写入。

我的猜测是,由于 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(中 - ofstream 完成,已将写入文件的责任移交给操作系统,但文件实际上尚未写入(因此,虽然 ofstream 可能是同步的,但文件的端到端写入,从数据到文件安全地写入磁盘,不是(。 鉴于我正在快速连续地进行大量写入(可能数千次(,这不一定有效。 操作系统可能会将手扔在空中并将大量文件写入掉在地板上(因此我最初要求以同步方式写入文件 - 端到端(。

我的解决方案是在每次写入后暂停,让操作系统有时间赶上进度。 虽然它不优雅,而且性能不如应有的水平 - 写入空文件不需要半秒钟。 此外,在慢速存储下,半秒可能不够。 我欢迎任何关于如何改进我的代码的聪明建议。

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;
}

最新更新