在 C++ 中写入不可靠磁盘时引发 I/O 错误
想象一下您在 C++ 中有以下内容:
ofstream myfile;
myfile.open (argv[1]);
if (myfile.is_open()){
for(int n=0;n<=10;n++){
myfile << "index="<<n<<endl;
sleep(1);
}
}else{
cerr << "Unable to open file";
}
myfile.close();
在写入时,您正在写入的磁盘或介质变得不可用,但在 close()
时又恢复正常,因此中间丢失了数据。或者想象一下,您向 USB 闪存驱动器写入数据,并且在写入过程中该设备被拔出并重新插入。
你怎么能检测到这一点?我尝试检查将写入放入 try {} catch
、flags()
、rdstate()
中,您可以说出它的名字,但到目前为止似乎没有一个去工作。
Imagine you have the following in C++:
ofstream myfile;
myfile.open (argv[1]);
if (myfile.is_open()){
for(int n=0;n<=10;n++){
myfile << "index="<<n<<endl;
sleep(1);
}
}else{
cerr << "Unable to open file";
}
myfile.close();
And while writing, the disk or medium you are writing to becomes unavailable but comes back on for the close()
so that you have missing data in between. Or imagine you write to a USB flash drive and the device is withdrawn and re-inserted during the writing process.
How can you detect that ? I tried checking putting the write in try {} catch
, flags()
, rdstate()
, you name it, but none thus far seem to work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不认为这是你可以在 stdio 级别检测到的东西。通常,当硬盘驱动器暂时停止响应时,操作系统将自动重试命令,直到成功或达到超时,此时您的系统调用可能会收到错误。 (OTOH,它可能不会,因为在数据写入内存文件系统缓存之后但在将任何命令发送到实际磁盘之前,您的调用可能已经返回)
如果您确实想检测flakey硬盘驱动器,您将可能需要编码到更低的级别,例如编写自己的硬件驱动程序。
I don't think that is something you can detect at the stdio level. Typically when a hard drive temporarily stops responding, the operating system will automatically retry the commands either until they succeed or a timeout is reached, at which point your system call may receive an error. (OTOH it may not, because your call may have returned already, after the data was written into the in-memory filesystem cache but before any commands were sent to the actual disk)
If you really want to detect flakey hard drive, you'll probably need to code to a much lower level, e.g. write your own hardware driver.
恕我直言,您可以尝试:
IMHO you can try to:
我不确定这是否会涵盖您的场景(在写入过程中删除 USB 驱动器),但您可以尝试在流上启用异常:
根据我的经验,iostreams 在使其难以检测错误和错误的类型。
I'm not sure if this will cover your scenario (removing a USB drive mid-write), but you can try enabling exceptions on the stream:
In my experience, iostreams do a "great" job of making it hard to detect errors and the type of error.
如果
std::ostream
由于任何原因失败,它会设置其状态位,然后检查该状态位,然后std::stream
处于布尔上下文中。这与检查 std::istream 是否正确将数据读入变量的方法相同。但是,这与您所说的 rdstate() 相同。如果是这种情况,则写入已到达缓冲区。
endl
,它刷新程序缓冲区,表明它位于操作系统的缓冲区中。从那里,您必须使用特定于操作系统的调用来强制它刷新缓冲区。[编辑]根据 http://msdn.microsoft .com/en-us/library/17618685(v=VS.100).aspx,如果您有文件,可以使用
_commit
强制刷新描述符。我找不到 std::ostream 的这样的保证。If the
std::ostream
fails for any reason, it sets it's state bit, which is checked then thestd::stream
is in a boolean context. This is the same way you check if anstd::istream
read in data to a variable correctly.However, this is the same as
rdstate()
, which you say you tried. If that's the case, the write has gotten to a buffer.endl
, which flushes the programs buffer, shows that it's in the Operating System's buffer. From there, you'll have to use OS-specific calls to force it to flush the buffer.[Edit] According to http://msdn.microsoft.com/en-us/library/17618685(v=VS.100).aspx, you can force a flush with
_commit
if you have a file descriptor. I can't find such a guarantee forstd::ostream
s.