使用ifstream::seekg和tellg获取文件大小

4

我有以下代码块来测试seekg和tellg函数在获取文件大小时的行为:

    int size = 0;
    ifstream in(fileName.c_str(), ifstream::in | ifstream::binary);
    if(in)
    {
        in.seekg(0,ifstream::end);
        size = in.tellg();
        cout << endl;
        cout << endl;
        cout << "********** size stream1*** =" << size << endl;
        in.seekg(0,ios::end);
        size = in.tellg();
        cout << "********** size stream2*** =" << size << endl;
        in.seekg(0,ios::end);
        size = in.tellg();
        cout << "********** size stream3*** =" << size << endl;
        in.seekg(100,ios::end);
        size = in.tellg();
        cout << "********** size stream4*** =" << size << endl;
        in.seekg(0,ios::beg);
        size = in.tellg();
        cout << "********** size stream5*** =" << size << endl;
        in.seekg(100);
        in.seekg(0, ios::end);
        size = in.tellg();
        cout << "********** size stream6*** =" << size << endl;
        in.seekg(100);
        in.seekg(0, ios::cur);
        size = in.tellg();
        cout << "********** size stream7*** =" << size << endl;
        in.seekg(-100,ios::end);
        size = in.tellg();
        cout << "********** size stream8*** =" << size << endl;
        in.seekg(ios::beg,ios::end);
        size = in.tellg();
        cout << "********** size stream9*** =" << size << endl;
        in.seekg(ios::beg);
        in.seekg(ios::end);
        size = in.tellg();
        cout << "********** size stream10*** =" << size << endl;
        cout << endl;
        cout << endl;
    }

以下是它的结果:

********** size stream1*** =1846
********** size stream2*** =1846
********** size stream3*** =1846
********** size stream4*** =1946
********** size stream5*** =0
********** size stream6*** =1846
********** size stream7*** =100
********** size stream8*** =1746
********** size stream9*** =1846
********** size stream10*** =2

我的问题如下:

  1. tellg 是否会返回上次 seekg 找到的字节?
  2. 为什么 stream5 的结果是0?它之前的位置在文件结尾。
  3. seekg 是否总是从文件开头开始,就像 stream5 中所示?
  4. seekg 不能像 stream5 中所示一样向后移动吗?
  5. seekg 的第一个参数真正意味着什么?它说它是第二个参数的偏移量。如果它是正值,则似乎它会超过第二个参数指向的位置,就像 stream4 中所示。
  6. 如果我想知道前100个字节后的大小,我必须使用 -100,就像 stream8 中所示吗?
  7. 为什么 stream10 是2?
  8. ofstream 中的 seekptellp 是否与这里的 seekgtellg 具有相同的属性?

tellg返回文件的当前位置。请阅读手册。顺便提一下,您只有一个流。 - Charlie Burns
2
在 stream5 之前,您调用了 in.seekg(0,ios::beg);。为什么它不应该是 0? - cen
对于第6个问题,为什么不直接获取完整大小并减去100呢?如果文件小于100字节,则可能会将位置设置在流的开头以下。我测试了一下,对于较小的文件,返回大小为-1,我认为这是failbit错误设置。 - cen
1个回答

6

好的,我们开始吧:

  1. tellg()会返回位置对象,可用于返回到当前位置。返回的类型是std::streampos,它是std::fpos<std::mbstate_t>。然而,std::fpos<std::mbstate_t>可以转换为整数std::streamoff。实际上,std::streampos表示从第一个位置到当前位置的字符数。
  2. 相对于std::ios_base::beg定位到0个字符明显将位置设置为文件开头。你是不是想使用std::ios_base::cur
  3. seekg()相对于起始位置、当前位置或结尾位置进行定位,具体取决于所谓的参数是std::ios_base::begstd::ios_base::cur还是std::ios_base::end
  4. 可以使用负偏移量向后移动。
  5. 参见3.:第一个参数是相对于whence参数指定的位置移动的偏移量。
  6. 不需要。如果知道文件中有多少个字符,可以将该数字减去100。
  7. 您使用了绝对定位,并将whence值作为位置。 std::ios_base::seekdir类型是一个枚举类型,std::ios_base::end可能具有值2
  8. 基本上没错。

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