为啥 c++ ifstream 不能从设备读取?

Posted

技术标签:

【中文标题】为啥 c++ ifstream 不能从设备读取?【英文标题】:Why can't c++ ifstreams read from devices?为什么 c++ ifstream 不能从设备读取? 【发布时间】:2008-10-06 11:01:24 【问题描述】:

我知道我不应该开始使用 c++ io,整个“类型安全”论点是一个红鲱鱼(有没有人真的发现这是他们最紧迫的问题之一?)。无论如何,我做到了,并发现了 ifstreams 和 FILE*s 以及普通的旧文件描述符之间的一个奇怪区别:ifstreams 无法从设备中读取。谁能想到原因?

const char* path = "/dev/disk3";
char        b;

// this works
FILE* f= fopen(path, "rb");
int i = fread(&b, 1, 1, f);     // returns 1, success!

// this does not work
ifstream    cf(path, ios::binary);
cf.read(&b, 1);
bool        good = cf.good();   // returns false, failure.

【问题讨论】:

FWIW,我认为您的题外话“大谎言”评论可能会阻止知识渊博的人回答这个问题。 操作系统和编译器版本可能会有所帮助... 我同意克里斯托弗·约翰逊的观点。我不知道答案,但我知道我不会觉得有必要去寻找它。 好吧,也许“大谎言”有点过于情绪化了。让我们看看我是否可以改变它。操作系统是豹10.5.5,gcc vers = 4.0.1 我有个不错的主意。但我不喜欢这种诱饵。 【参考方案1】:

对我来说很好,它不是你想象的 C++ 流文件 I/O 固有的问题。

也许尝试将ios::in 添加到打开模式标志。根据标准的 27.8.1.6,它需要或与 ios::in 一起使用,所以这可能不会做任何事情。

尝试检查实际设置了哪个位 - 不要调用 good(),而是尝试分别检查 bad()、eof() 和 fail()。这可能会提供关于错误是什么的线索。

【讨论】:

适用于您的实现而不是我的 = 不可移植。我“降级”到 FILE* 并且一切正常。 Adios c++ 流,不能说很高兴认识你。 之后,标志是好的 = 0 eof = 0 fail = 1 并且... perror 说“无效的参数”。我想知道为什么。 变得有趣,不是吗?几乎和“Kon and Bal”一样有趣。【参考方案2】:

设备是无缓冲的,必须以 512 字节的倍数读取。 ifstream 做它自己的缓冲并且奇怪地决定提前读取 1023 个字节,这会因“无效参数”而失败。有趣的是,这个 ifstream 是在 FILE* 之上实现的。但是,留给自己设备的 FILE* 使用更好、更圆的字节数进行预读。

感谢 dtrace 提供重要线索。我想我们永远不会知道那些认为他们知道答案但不想说的人是否正确。

【讨论】:

因此,换句话说,FILE* 版本只是由于缓冲区大小的底层选择而偶然工作。如果您可以控制 C++ 流的缓冲区大小,那么它可能也可以正常工作。 basic_filebuf::setbuf 函数看起来可能是相关的。 完全正确,FILE* 只能靠运气,所以我掉到了文件描述符界面。不过,在删除所有 iostream 代码之前。我不会错过它。希望这对 SO-09 不会太刺激!感谢您的评论。【参考方案3】:

多年来,我在 C++ I/O 中发现了类似的随机问题。对我来说,这似乎是一种倒退。

我还没有尝试过,但您可能想看看 Boost 提供了什么:

http://www.boost.org/doc/libs/1_36_0/libs/iostreams/doc/index.html

【讨论】:

以上是关于为啥 c++ ifstream 不能从设备读取?的主要内容,如果未能解决你的问题,请参考以下文章

c++ 从具有相同循环的 ifstream 或 stringstream 中读取

为啥我在使用 ifstream 通过命名管道读取一行后得到 EOF?

c++ 为啥 ifstream get() 函数返回无法识别的特殊字符?

C++ Ifstream 读取太多?

C++,读取二进制 ifstream 时的奇怪行为

c++中ifstream一次读取整个文件