设为首页 加入收藏

TOP

15.3.1 通过seek()和tell()在文件中转移
2013-10-07 15:35:37 来源: 作者: 【 】 浏览:69
Tags:15.3.1 通过 seek tell 文件 转移

15.3.1  通过seek()和tell()在文件中转移

所有的输入和输出流都有seek()和tell()方法,但是在文件流的上下文之外很少有意义。

seek()方法允许在输入或输出流中移动到任意位置。seek()有好几种形式。输入流中的seek()方法实际上称为seekg()(g表示get的意思),输出流中seek()的版本称为seekp()(p表示put的意思)。您可能想知道为什么同时存在seekg()和seekp()方法,而不是一个seek()方法。原因是有的流既可以输入又可以输出,例如文件流。在这种情况中,流需要记住一个读位置和一个独立的写位置。另外还有本章后面讨论的双向I/O。

seekg()和seekp()有两个重载。一个重载接受一个参数:绝对位置,这个重载定位到这个绝对位置。另一个重载接受一个偏移量和一个位置,这个重载定位到给定位置相对偏移量的位置。位置的类型为ios_base::streampos,偏移量的类型为ios_base::streamoff,这两个类型都以字节计数。预定义的三个位置如表15-3所示。

表  15-3

    < xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

   

ios_base::beg

表示流的开头

ios_base::end

表示流的结尾

ios_base::cur

表示流的当前位置

例如,要定位到输出流的一个绝对位置,可以使用接受一个参数的seekp()版本,如下例所示,这个例子通过ios_base::beg常量定位到流的开头位置:

  1. outStream.seekp(ios_base::beg); 

在输入流中定位完全一样,只不过用的是seekg()方法:
  1. inStream.seekg(ios_base::beg); 

接受两个参数的版本定位到流中的相对位置。第一个参数表示要移动的位置数,第二个参数表示起始点。要相对文件起始位置移动,使用ios_base::beg常量。要相对文件末尾位置移动,使用ios_base::end常量。要相对文件当前位置移动,使用ios_base::cur常量。例如,下面这行代码从流起始位置移动到第二个字节。注意,整数被隐式地转换为ios_base::streampos和ios_base::streamoff类型:
  1. outStream.seekp(2, ios_base::beg); 

下面这个例子转移到输入流中倒数第3个字节:

  1. inStream.seekg(-3, ios_base::end); 

可以通过tell()方法查询流的当前位置,这个方法返回一个表示当前位置的ios_base::streampos值。利用这个结果,可在进行seek()之前记住当前标记的位置,还可以查询是否在某个特定的位置。和seek()一样,输入流和输出流也有不同版本的tell()。输入流使用的是tellg(),输出流使用的是tellp()。

下面的代码检查输入流的当前位置,并判断是否在起始位置:

  1. ios_base::streampos curPos = inStream.tellg();  
  2. if (ios_base::beg == curPos) {  
  3. cout << "We're at the beginning." << endl;  
  4. }  

下面是一个整合了所有内容的示例程序。这个程序写入一个名为test.out的文件,并且执行以下测试:

(1) 将字符串12345输出至文件。

(2) 验证标记在流中的位置5。

(3) 转移到输出流的位置2。

(4) 在位置2输出0,并关闭输出流。

(5) 在文件test.out文件上打开输入流。

(6) 将第一个标记以整数的形式读入。

(7) 确认这个值是否为12045。

  1. ofstream fout("test.out");  
  2. if (!fout) {  
  3. cerr << "Error opening test.out for writing" << endl;  
  4. return 1;  
  5. }  
  6. // 1. Output the string "12345".  
  7. fout << "12345";  
  8. // 2. Verify that the marker is at position 5.  
  9. ios_base::streampos curPos = fout.tellp();  
  10. if (5 == curPos) {  
  11. cout << "Test passed: Currently at position 5" << endl;  
  12. } else {  
  13. cout << "Test failed: Not at position 5" << endl;  
  14. }  
  15. // 3. Move to position 2 in the stream.  
  16. fout.seekp(2, ios_base::beg);  
  17. // 4. Output a 0 in position 2 and close the stream.  
  18. fout << 0;  
  19. fout.close();  
  20. // 5. Open an input stream on test.out.  
  21. ifstream fin("test.out");  
  22. if (!fin) {  
  23. cerr << "Error opening test.out for reading" << endl;  
  24. return 1;  
  25. }  
  26. // 6. Read the first token as an integer.  
  27. int testVal;  
  28. fin >> testVal;  
  29. // 7. Confirm that the value is 12045.  
  30. const int expected = 12045;  
  31. if (testVal == expected) {  
  32. cout << "Test passed: Value is " << expected << endl;  
  33. } else {  
  34. cout << "Test failed: Value is not " << expected 
  35. << " (it was " << testVal << ")" << endl;  
  36. }  
  37.  
  38. 代码取自FileStream\FileStream2.cpp  
  39.  

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇5.7 风格的挑战 下一篇15.1.2 流的来源和目标

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·哈希表 - 菜鸟教程 (2025-12-24 20:18:55)
·MySQL存储引擎InnoDB (2025-12-24 20:18:53)
·索引堆及其优化 - 菜 (2025-12-24 20:18:50)
·Shell 中各种括号的 (2025-12-24 19:50:39)
·Shell 变量 - 菜鸟教 (2025-12-24 19:50:37)