【问题标题】:seekp before writing?在写作之前寻找?
【发布时间】:2013-03-06 06:24:12
【问题描述】:

我想用一个文件流读写一个二进制文件。以下代码尝试读取文件的第一部分,并使用它来覆盖文件的第二部分。但我发现我必须使用“seekp(pos [,ios_base::begin]);”在写作之前。此外,“seekp”实际上并没有改变我代码中的位置,但它是必要的!任何人都可以解释一下吗?它应该更好地根据 c++ 标准。非常感谢!

#include <iostream>
#include <fstream>
using namespace std;

int main(){
    fstream flib ("tmp.txt", ios::in | ios::out |ios::binary | ios::trunc);
    if(!flib){
        cerr << "file open failed!" << endl;
        return 1;
    }
    int tmp;

    for(int i = 0; i<2 ; i++){//write 2 numbers
        flib.write((char*)&i, sizeof(tmp));
    }
    flib.seekg(0);
    while(flib.read((char*)&tmp, sizeof(tmp))){//read file contents
        cout <<tmp<<endl; 
    }
    flib.clear();
    flib.seekg(0);
    flib.read((char*)&tmp, sizeof(tmp));
    flib.seekp(sizeof(tmp)); //work
    //flib.seekp(sizeof(tmp), ios_base::beg); //work
    //flib.seekp(0, ios_base::cur); //not work
    //flib.seekp(sizeof(tmp), ios_base::end); //not work
    //flib.seekp(-sizeof(tmp), ios_base::end); //not work
    flib.write((char*)&tmp, sizeof(tmp));
    flib.clear();
    flib.seekg(0);
    while(flib.read((char*)&tmp, sizeof(tmp))){//read file contents
        cout <<tmp<<endl; 
    }

    return 0;
 }

评论:我发现如果我使用 flib.seekp(some_number, ios_base::cur);使用非零 some_number,它可以工作。而且我用的是vs2012 express编译器,是不是bug?

【问题讨论】:

  • flib.seekp(0, ios_base::cur) 究竟应该做什么?而flib.seekp(sizeof(tmp), ios_base::end); 不应该工作,因为你试图寻找结束
  • "flib.seekp(0, ios_base::cur)" 应该等价于 "flib.seekp(sizeof(tmp));",对吧? “flib.seekp(sizeof(tmp), ios_base::end);”可能是错的,但为什么不“flib.seekp(-sizeof(tmp), ios_base::end);”工作吗?
  • 这是必要的,因为标准是这样说的。每当您从读取切换到写入或反之亦然(同一个文件)时,您都需要在两者之间进行查找或倒带。我相信这主要是为了给它一个刷新缓冲数据的机会,但我最近还没有仔细查看相关代码来确定。
  • flib.seekp(0, ios_base::cur) 说“从当前位置寻找零字节”,所以它实际上应该什么都不做(所以它与flib.seekp(sizeof(tmp)) 不同,它说“移动到这个绝对位置”(就像flib.seekp(sizeof(tmp), ios_base::beg)))。至于flib.seekp(-sizeof(tmp), ios_base::end),我们得看看你是怎么称呼它的,因为它是Works For Me
  • @user 是的,尺寸类型是无符号的。使用-(int)sizeof(tmp)-(long)sizeof(tmp)

标签: c++ fstream


【解决方案1】:

文件流使用basic_filebuf&lt;&gt; 作为流缓冲区。 C++03 标准对class basic_filebuf&lt;charT,traits&gt; 有这样的说法:

27.8.1.1 类模板 basic_filebuf

basic_filebuf 类将两个输入关联起来 序列和带有文件的输出序列。

对由一个控制的序列的读写限制 类 basic_filebuf 的对象与 for 相同 使用标准 C 库FILEs 读写。

特别是: - 如果文件未打开以进行读取,则无法读取输入序列。 - 如果文件未打开以进行写入,则无法写入输出序列。 - 为输入序列和输出序列维护一个联合文件位置。

不幸的是,当使用标准 C 库在读取和写入 FILE 对象之间转换时,您必须执行文件定位调用(或在从写入操作转换到读取时执行 fflush()操作)。见https://stackoverflow.com/a/14879076/12711

【讨论】:

    猜你喜欢
    • 2020-12-05
    • 1970-01-01
    • 2021-12-02
    • 2023-03-10
    • 1970-01-01
    • 2023-01-17
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多