C++文件流与字符串流使用详解
C++的I/O类库提供了丰富的流机制,本文将深入解析C++文件流(用于磁盘文件)和字符串流(用于内存字符数组)的核心概念、类的派生关系及具体操作方法。
C++文件流基础与操作
文件流是以外存文件为输入输出对象的数据流。需要明确区分文件流与文件的概念:文件流本身不是文件,而是以文件为对象的媒介。每个文件流都对应一个内存缓冲区。
在C++ I/O类库中,除了标准的 istream、ostream 和 iostream 类外,还有三个专门用于文件操作的文件类:
- ifstream 类:从
istream派生,支持从磁盘文件输入。 - ofstream 类:从
ostream派生,支持向磁盘文件输出。 - fstream 类:从
iostream派生,支持对磁盘文件的输入和输出。
由于使用磁盘文件的情况各异,无法像 cin 和 cout 那样预先统一定义,用户必须自己定义文件流对象。建立输出文件流对象的语法如下:
ofstream outfile;
此语句定义了 outfile 为 ofstream 类的对象。但与 cout 不同,此时尚未指定它具体向哪个磁盘文件输出,需要在后续操作中通过打开文件或构造函数来关联具体的文件路径。
C++字符串流的原理与实现
字符串流不是以外存文件为对象,而是以内存中用户定义的字符数组(字符串)为输入输出对象,因此也被称为内存流。其核心特点如下:
- 缓冲区机制:字符串流拥有独立的流缓冲区。写入时数据先存入缓冲区,满或遇换行符后一起存入字符数组;读取时数据先从数组送入缓冲区,再提取给变量。
- 数据转换:写入前将二进制数据转换为ASCII码存入缓冲区,读出前再将ASCII码转换回二进制形式赋给变量。
- 无文件开关:字符串流关联的是字符数组而非文件,因此不需要也不支持
open()和close()成员函数。 - 结束标志:不同于文件流的文件结束符,字符串流需用户指定特殊字符(如
'\0')作为结束标志。
字符串流类包括 istrstream(输入)、ostrstream(输出)和 strstream(输入输出),它们均在 <strstream> 头文件中定义(GCC中使用 <strstream>)。
第1步:建立输出字符串流对象 (ostrstream)
目的:将数据格式化地写入指定的字符数组。
构造函数原型:ostrstream::ostrstream(char *buffer, int n, int mode = ios::out);
buffer:指向字符数组首元素的指针。n:流缓冲区的大小(通常与字符数组大小相同,也可不同)。mode:默认值为ios::out。
示例代码:
char ch1[20];
ostrstream strout(ch1, 20); // 建立输出串流,关联数组ch1,缓冲区长20
第2步:建立输入字符串流对象 (istrstream)
目的:从指定的字符数组中按数据类型读取数据。
构造函数原型:istrstream::istrstream(char *buffer);istrstream::istrstream(char *buffer, int n);
- 若无参数
n,则读取整个字符数组的内容。 - 若指定
n,则仅读取前n个字符作为流内容。
示例代码:
char ch2[50] = "12 34 65";
istrstream strin(ch2, sizeof(ch2)); // 读取全部数据
// 或
istrstream strin_partial(ch2, 10); // 仅读取前10个字符
第3步:建立输入输出字符串流对象 (strstream)
目的:对同一字符数组进行交叉读写操作。
构造函数原型:strstream::strstream(char *buffer, int n, int mode);
示例代码:
char ch3[50];
strstream strio(ch3, sizeof(ch3), ios::in | ios::out); // 同时支持读写
字符串流实战应用示例
以下两个示例展示了字符串流在处理结构化数据和排序算法中的应用。
示例1:向字符数组写入结构化数据
本例将学生数据写入字符数组 c,并观察缓冲区大小的影响。
#include <strstream>
#include <iostream>
using namespace std;
struct student {
int num;
char name[20];
float score;
};
int main() {
student stud[3] = {1001, "Li", 78, 1002, "Wang", 89.5, 1004, "Fun", 90};
char c[50];
// 建立输出字符串流,关联数组c,指定缓冲区大小为30
ostrstream strout(c, 30);
for(int i = 0; i < 3; i++) {
strout << stud[i].num << stud[i].name << stud[i].score;
}
strout << ends; // 插入 '\0' 结束符
cout << "array c:" << c << endl;
return 0;
}
运行结果:
array c: 1001Li781002Wang89.51004Fun90
注意:
- 数据之间没有空格,连成一片,后续直接读取可能会混淆数据边界。
- 若将缓冲区大小改为10(即
ostrstream strout(c, 10);),则只能输出前10个字符:1001Li7810。这证明了缓冲区大小限制了实际传输的数据量。 - 建议在输出时人为加入分隔符(如空格),以便后续正确读取。
示例2:从字符数组读取、排序并写回
本例从包含整数的字符数组中读取数据,排序后再写回原数组。
#include <strstream>
#include <iostream>
using namespace std;
int main() {
char c[50] = "12 34 65 -23 -32 33 61 99 321 32";
int a[10], i, j, t;
cout << "array c:" << c << endl;
// 建立输入串流
istrstream strin(c, sizeof(c));
for(i = 0; i < 10; i++) {
strin >> a[i]; // 自动识别整数类型
}
cout << "array a:";
for(i = 0; i < 10; i++) cout << a[i] << " ";
cout << endl;
// 冒泡排序
for(i = 0; i < 9; i++)
for(j = 0; j < 9 - i; j++)
if(a[j] > a[j+1]) {
t = a[j]; a[j] = a[j+1]; a[j+1] = t;
}
// 建立输出串流写回数组c
ostrstream strout(c, sizeof(c));
for(i = 0; i < 10; i++) {
strout << a[i] << " ";
}
strout << ends; // 添加结束符
cout << "array c:" << c << endl;
return 0;
}
运行结果:
array c: -32 -23 12 32 33 34 61 65 99 321
关键点:
- 字符串流能自动处理类型转换(如字符串到整数),比逐个访问字符数组更灵活。
- 输出时重新覆盖了字符数组
c的内容。 - 输入和输出流可以分别指向同一数组的不同部分或交叉操作,互不干扰(通过各自的流指针)。
总结与建议
字符串流在C++中充当了内存中的临时仓库,适用于需要快速进行格式化和非格式化数据转换的场景。相比磁盘文件,它具有无需打开/关闭文件、存取速度快、使用简便的优点。但其生命周期受限于所在模块(如主函数),不能作为持久化存储手段。在实际开发中,应注意缓冲区大小限制和数据分隔符的使用,以确保读写的准确性。
以上就是C++文件流与字符串流使用的详细内容,更多关于C++ I/O高级操作的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









