13.3文件流

13.3文件流


<fstream>定义的 std::ofstreamstd::ifstream类提供了文件的输入输出功能.

输出文件流和其他输出流的唯一主要区别在于∶文件流的构造函数可以接收文件名以及打开文件的模式作为参数。默认模式是写文件(ios_base::app),这种模式从文件开头写文件,改写任何已有的数据。

常量说明
ios_base::app打开文件, 在每一次写操作之前, 移到文件末尾(追加模式)
ios_base::ate打开文件, 打开之后立即移到文件末尾
ios_base::binary以二进制模式执行输入输出操作(相对于文本模式)
ios_base::in打开文件, 从开头开始读取
ios_base::out打开文件, 从开头开始写入, 覆盖已有的数据
ios_base::trunc打开文件, 并删除(截断)任何已有数据

上述选项可以组合使用, 用|分隔开即可

ios_base::app | ios_base::in | ios_base::ate

ifstream默认ios_base::in模式, ofstream默认ios_base::out模式

1.文本模式与二进制模式

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

所有的输入流和输出流都有 seekx()和tellx()方法。seekx()方法允许在输入流或输出流中移动到任意位置。seek(), tell()有好几种形式。

  • 对于输入流,这个方法实际上称为 seekg(), tellg()(g 表示 get);
  • 对于输出流, 这个方法实际上称为seekp(), tellp()(p表示put)。

为什么同时存在seekg()seekp()方法,而不是seek()方法?原因是有的流既可以输入又可以输出,例如文件流。在这种情况下,流需要记住读位置和独立的写位置。这也称为双向 I/O(bidirectional I/O)

seekg()seekp()有两个重载版本。其中一个重载版本接收一个实参∶绝对位置。这个重载版本将定位到这个绝对位置。另一个重载版本接收一个偏移量和一个位置,这个重载版本将定位到距离给定位置一定偏移量的位置。位置的类型为 std::streampos,偏移量的类型为 std::streamoff,这两种类型都以字节计数。预定义的3个位置如下:

位置说明
ios_base::beg表示流的开头
ios_base::end表示流的结尾
ios_base::cur表示流的当前位置

示例:

  • (1)将字符串54321输出至文件。
  • (2)验证标记在流中的位置5。
  • (3)转移到输出流的位置2。
  • (4)在位置2输出0,并关闭输出流。
  • (5)在文件 test.out 上打开输入流。
  • (6)将第一个标记以整数的形式读入。
  • (7)确认这个值是否为54021。
ofstream fout { "test.out" };
if(!fout) {
  cerr << "Error opening test.out for writing" << endl;
  return 1;
}

// 1. Output the string "54321".
fout << "54321";

// 2.Verify that the marker is at position 5.
streampos curPos { fout.tellp() };
if(curPos == 5) {
  cout << "Test passed: Currently at position 5" << endl;
} else {
  cout << "Test failed: Not at position 5" << endl;
}

// 3. Move to position 2 in the output stream.
fout.seekp(2, ios_base::beg);

// 4. Output a 0 in position 2 and close the output stream.
fout << 0;
fout.close();

// 5. Open an input stream on test.out.
ifstream fin { "test.out" };
if(!fin) {
  cerr << "Error opening test.out for reading." << endl;
  return 1;
}

// 6. Read the first token as an integer.
int testVal;
fin >> testVal;
if(!fin) {
  cerr << "Error reading from file" << endl;
  return 1;
}

// 7. Confirm that the value is 54021.
const int expected { 54021 };
if(testVal == expected) {
  cout << format("Test passed: Value is {}", expected) << endl;
} else {
  cout << format("Test failed: Value is not {} (it was {})", 
                expected, testVal) << endl;
}

3.将流链接在一起

任何输入流和输出流之间都可以建立链接,从而实现"访问时刷新((flush-on-access)"的行为。换句话说,当从输入流请求数据时,链接的输出流会自动刷新。这种行为可用于所有流,但对于可能互相依赖的文件流来说特别有用。

通过 tie()方法完成流的链接。要将输出流链接至输入流,对输入流调用tie()方法,并传入输出流
的地址。要解除链接,需要传入nullptr

ifstream inFile { "input.txt" }; // Note: input.txt must exist
ofstream outFile { "output.txt" };
inFile.tie(&outFile);
outFile << "Hello there!";
string nextToken;
inFile >> nextToken;
// outFile HAS been flushed.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值