在C++编程中,有一个核心类叫做stream,它是所有输入输出操作的基础,包括文件输入输出。这个类有两个重要的运算符:插入器(<<)和析取器(>>)。
我们来谈谈插入器。它是用于向流输出数据的。例如,系统默认的标准输出流是cout,通常指的是显示器。表达式"cout << "Write Stdout" << 'n';"会将字符串"Write Stdout"和换行字符('n')输出到标准输出流。
接下来是析取器,它用于从流中输入数据。例如,系统默认的标准输入流是cin,通常指的是键盘。表达式"cin >> x;"表示从标准输入流中读取指定类型(即变量x的类型)的数据。
在C++中,对文件的操作是通过stream的子类fstream(文件流)来实现的。要进行文件操作,必须包含fstream头文件。下面我们将详细介绍文件操作的流程。
一、打开文件
在fstream类中,有一个成员函数open()用于打开文件,其原型为:void open(const char filename, int mode, int access);
参数说明:
filename:要打开的文件名
mode:打开文件的方式
access:打开文件的属性
打开文件的方式在ios类(所有流式I/O类的基类)中定义。常用的值有:ios::app(以追加方式打开文件)、ios::ate(文件打开后定位到文件尾)、ios::binary(以二进制方式打开文件)、ios::in(文件以输入方式打开)、ios::out(文件以输出方式打开)、ios::nocreate(不建立文件)、ios::noreplace(不覆盖文件)和ios::trunc(如果文件存在,将其长度设为0)。可以使用“或”将这些属性连接起来,例如ios::out|ios::binary。
打开文件的属性取值可以是普通文件、只读文件、隐含文件或系统文件等。可以使用“或”或“+”将这些属性连接起来,例如以只读和隐含属性打开文件可以表示为3或1|2。
例如,以二进制输入方式打开文件c:config.sys的示例代码如下:
```cpp
fstream file1;
file1.open("c:\\config.sys", ios::binary | ios::in, 0);
```
fstream还有与open()相同的构造函数,可以在定义时就打开文件,例如:fstream file1("c:\\config.sys");。fstream还有两个子类:ifstream(输入文件流)和ofstream(输出文件流),前者默认以输入方式打开文件,后者默认以输出方式打开文件。因此在实际应用中,可以根据需要选择不同的类来定义。例如:ifstream file2("c:\\pdos.def"); // 以输入方式打开文件 ofstream file3("c:\\x.123"); // 以输出方式打开文件。
二、关闭文件
使用完打开的文件后一定要关闭。fstream提供了成员函数close()来完成此操作,例如:file1.close();就关闭与file1相关联的文件。
三、读写文件
一、十六进制与浮点数的输出
要将数字123以十六进制形式输出,可以这样操作:将数据输入流指向一个文件,然后使用特定函数进行格式化输出。例如,使用`<<`操作符和相应的格式化标签。代码示例如下:
```
file1 << std::hex << 123; // 将123以十六进制形式输出到file1文件中
```
若要将浮点数3.1415926以5位精度输出,可以这样操作:先设置精度,然后将浮点数输出。代码示例如下:
```
file1 << std::setprecision(5) << 3.1415926; // 设置精度为5位,并输出3.14159到file1文件中
```
二、二进制文件的读写操作
1. `put()`函数的使用
`put()`函数用于向流中写入一个字符。其原型为`ofstream::put(char ch)`。例如,向流中写入字符'c'的代码如下:
```
file1.put('c'); // 向file1流中写入字符'c'
```
2. `get()`函数的使用
`get()`函数用于从流中读取字符。它有几种重载形式,包括读取一个字符并保存到引用中的形式,以及返回一个字符的形式。例如:
```
char ch;
file2.get(ch); // 从file2流中读取一个字符,并保存到变量ch中
```
或者:
```
int x;
x = file2.get(); // 从file2流中读取一个字符,并返回其ASCII值
```
还有一种是读取字符到数组中的形式,可以指定读取的字符数量或遇到特定分隔符时停止读取。例如:
```
char str1[128];
file2.get(str1, 127, 'A'); // 从file2流中读取字符到str1数组,最多读取127个字符或遇到字符'A'时停止
```
3. 读写数据块的操作
对于读写数据块,可以使用`read()`和`write()`成员函数。这些函数的原型如下:
```
read(unsigned char buf, int num); // 从文件中读取num个字符到buf指向的缓存中
write(const unsigned char buf, int num); // 从buf指向的缓存写num个字符到文件中
```
举例来说:
```
unsigned char str1[] = "我爱你"; // 定义一个二进制字符串数组
int n[5]; // 定义一个整数数组用于存储数据块信息
// ...(省略将str1全部写入文件yyy.yyy的代码)...
// ...(省略从xxx.xxx文件中读取指定个数整数n的代码)... 检测EOF成员函数的使用 eof()成员函数用于检测是否已经到达文件末尾。如果到达文件末尾,则返回非零值;否则返回0。使用示例如下:
if (in.eof()) {
ShowMessage("已经到达文件尾!");
} ``` 文件定位的操作涉及到`seekg()`和`seekp()`两个成员函数,分别用于设置读位置和写位置。这两个函数的使用方式如下: ``` c++ p>istream::seekg(streamoff offset, seek_dir origin); // 设置读位置 p>ostream::seekp(streamoff offset, seek_dir origin); // 设置写位置 ``` 其中,`streamoff`定义了偏移量的最大值,`seek_dir`表示移动的基准位置(如文件开头、当前位置或文件结尾)。在实际编程中,这两个函数一般用于二进制文件的操作,因为文本文件可能会因系统对字符的解释不同而出现预期外的结果。 文件定位的进一步操作还包括使用`tellg()`函数返回当前指针位置,以及使用`seekg()`和`tellg()`配合进行指针的相对定位和绝对定位。例如: ``` c++ p>datafile.seekg(-20L, ios::cur); // 将文件定位指针从当前位置向后移20个字节 p>datafile.seekg(20L, ios::beg); // 将文件定位指针从文件头向后移20个字节 p>datafile.seekg(-20L, ios::end); // 将文件定位指针从文件尾向前移20个字节 ``` tellg()`和`seekg()`常常一起使用,以便精确控制文件的读写位置。 需要注意的是,在实际的C++编程中,有时可能会使用如何随机读取文件中的某一行?
对文件进行随机读取,我们需要先获取一个随机数,然后用这个随机数作为行号来读取相应的行。但需要注意的是,文件的第一行是0行,第二行是1行,以此类推。我们需要在获取随机数后,将其转换为相应的行号。
下面是一个使用C++编写的示例代码,展示了如何随机读取文件中的某一行:
```cpp
#include
#include
#include
int main() {
std::fstream ioFile("example.txt", std::ios::in);
if (!ioFile) {
std::cout << "Error in trying to open file";
return 0;
}
// 获取一个随机数
int randomLine = std::rand() % ioFile.lines(); // lines() 函数返回文件中的行数
// 将随机数转换为行号(文件的第一行是0行)
randomLine = (randomLine == 0) ? ioFile.lines() - 1 : randomLine - 1;
// 跳转到指定行并读取该行内容
ioFile.seekg(randomLine, std::ios::beg);
std::string line;
std::getline(ioFile, line);
std::cout << "Randomly selected line: " << line;
return 0;
```
在这个示例中,`std::rand()`函数用于生成一个随机数,`std::ios::in`表示以输入模式打开文件,`std::getline()`函数用于读取文件中的一行内容。`std::cout`用于将读取的内容打印到控制台。