流随机访问

各种流类型通常都支持对流中数据的随机访问。但绝大多数系统中绑定到 cin、cout、cerr、clog 的流不支持随机访问。

seek 和 tell 函数

函数 说明
tellg 返回输入流中标记的当前位置
tellp 返回输出流中标记的当前位置
seekg(pos) 在一个输入流中将标记重定位到给定的绝对地址
seekp(pos) 在一个输出流中将标记重定位到给定的绝对地址
seekg(off,from) 在一个输入流中将标记重定位到给定 from 的偏移量为 offset 的位置
seekp(off,from) 在一个输出流中将标记重定位到给定 from 的偏移量为 offset 的位置

上面 from 的取值可以是:

  • beg,偏移量相对于流开始位置。
  • cur,偏移量相对于流当前位置。
  • end,偏移量相对于流结尾位置。

注意:

  • g 版本用于读取的数据,理论上来讲只能对 istream 和派生自 istream 的类型 ifstream 和 istringstream 使用 g 版本。
  • p 版本用于写入的数据,理论上来讲对 ostream 和派生自 ostream 的类型 ofstream 和 ostringstream 使用 p 版本。
  • fstream 和 stringstream 既能读又能写,因此这些类型既可以使用 g 版本也可以使用 p 版本。

只有一个标记

标记只有一个,并不存在独立的读标记和独立的写标记。

重定位标记

  • pos 的类型是 pos_type,表示一个文件位置。
  • offset 的类型是 off_type,表示一个偏移量,可以是正的也可以是负的,表示向前、向后移动。

读写同一个文件

int main(void)
{
	fstream inOut("test.txt", fstream::ate | fstream::in | fstream::out);
	if (!inOut)
	{
		cerr << "Unable to open file" << endl;
		return EXIT_FAILURE;
	}

	auto end_mark = inOut.tellg();  //@ ate 模式打开,因此是文件末尾位置
	inOut.seekg(0, fstream::beg);	//@ 重定位到文件首位置
	size_t cnt = 0;
	string line;

	while (inOut && inOut.tellg() != end_mark && getline(inOut, line))
	{
		cnt += line.size() + 1;			//@ +1 表示换行符
		auto mark = inOut.tellg();		//@ 记录当前的读取位置
		inOut.seekp(0,fstream::end);	//@ 写指针移动到文件尾
		inOut << cnt;					//@ 写入累计长度
		if (mark != end_mark) inOut << " ";
		inOut.seekg(mark);				//@ 恢复到读位置
	}

	inOut.seekp(0, fstream::end);	    //@ 定位到文件尾
	inOut << "
";						//@ 在文件尾输出一个换行符

	return 0;
}

test.txt 原来的内容:

abcd
efj
hi
j

修改后的内容:

abcd
efj
hi
j
5 9 12 14
原文地址:https://www.cnblogs.com/xiaojianliu/p/12404832.html