我需要使用ifstream每次读取后都要寻找吗?

3

这是我用于从任意大小的文件中读取并写入到1016字节char*数据包的循环,每次写入1016个字节,然后发送它(发送未包含在内)。

seekg()是否必要?或者说读取已经将指针移动到下一个块的开头了吗?

ifstream file (packet.message, ios::in|ios::binary|ios::ate);
if(file.is_open()) {
    size = file.tellg();
    file.seekg(0, ios::beg);
    for(int i = 0; !ios::eof; i++) {
        memset(packet.message,0,1016*sizeof(char));
        file.read(packet.message,1016*sizeof(char));
        file.seekg(i*1016*sizeof(char));
    }
}

我知道这对于写入文件来说不是问题,因为你可以一直写到结尾,直到文件大小正好。

编辑:在if语句中添加了整段代码。


你的话好像创建一个C++程序很难一样。每次回答关于C++的问题时,我倾向于写、编译和运行一个小程序(主要是因为我不经常使用C++,不想发布不能编译的代码示例)。 - Brendan Long
@BrendanLong 在某些情况下,这是一个很好的建议,但在C和C++中,由于实现定义和未定义行为的问题,它经常失败。 - user395760
@DanielKO 我应该使用什么替代eof()呢? - Portaljacker
read() 返回流对象,因此您可以测试它以查看操作是否成功。就像“while (file.read(....)) { ... }”一样,这是通常的用法。 - DanielKO
@DanielKO 那么将该行代码移至循环语句内部并在其中执行即可。我猜我的memset必须放在循环迭代的末尾,因为我不想在发送数据包之前擦除它。 :P - Portaljacker
显示剩余6条评论
2个回答

7

这并不是必须的。读取文件时,会从上次看到文件指针的位置继续进行,就像写入一样。


谢谢,我想现在可以变成一个 while 循环了! - Portaljacker
1
@Portaljacker - 你也可能不需要在循环之前进行查找。 - Robᵩ
@Robᵩ我之所以把它放在那里,是因为示例中显示了它。我没有展示在使用tellg()保存大小之前的那一行。我假设tellg()移动了指针。 - Portaljacker
tellg() 没有问题,但是听起来你之前使用了 seekg()。在这种情况下,你可能需要重置回开头。 - Robᵩ
@Robᵩ 我得到这个例子很奇怪...它做了我在例子中所做的事情,tellg然后seekg到0。它说tellg给出指针的当前位置,如果指针在文件末尾,那么它将是大小,对吗?相关教程:http://www.cplusplus.com/doc/tutorial/files/ - Portaljacker

0
我敢打赌文件没有在std::ios_base::binary模式下打开,同时memset()seekg()被用于掩盖其结果:虽然两者都没必要,但如果它读取了一部分记录,则可能需要清除文件末尾的尾随字节。

顺便说一句:你总是想在读取之后检查数据流的状态:

while (in.read(buffer, size)) {
    ...
}

此外:sizeof(char) == 1

你是在说这是新写的代码吗?删除所有调用seekg()(你甚至没有使用size,更不用说它可能会给你错误的结果了,例如,如果使用非C++ std::codecvt<char> facet)。另外,删除memset():数据会被read()覆盖,虽然你可能需要验证一下读取的数据量是否符合预期。...而且你的循环条件显然是错误的,应该是file.read(...) - Dietmar Kühl
memset用于确保在写入数据之前将数据包清零。Size用于其他目的,但其位置很重要,因为在传输之前我必须将大小发送到另一台机器。就像我说的,我没有放置任何网络代码,只是在此之前将内容移入数据包中。 - Portaljacker
memset()是无意义的,因为除了最后一个数据包可能会被覆盖外,所有字节都会被read()覆盖!您可以使用gcount()设置未写入的尾随字节:while (file.read(buffer, size)) { std::fill(buffer + file.gcount(), buffer + size, 0); send(buffer, size); }。寻找文件结尾是否给出了大致的大小是几乎没有定义的。寻找的结果可用于恢复位置。对寻址位置进行计算确实有效,但您至少需要获取结束和开始之间的差异。 - Dietmar Kühl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接