[C++ Programming] Chapter 8: File Operation

Table of contents

1. Basic concepts of files and file stream classes

(1) The concept of files 

(2) C++ file stream class 

2. Open and close files

(1) Open the file 

(2) Close the file 

3. File read and write operations

(1) Read and write text files

(2) Read and write binary files 

① Write a file with the ostream::write() member function

② Use the istream::read() member function to read the file

③ Use the ostream::gcount() member function to get the number of read bytes

(3) Use member functions put() and get() to read and write files

① int get();

② istream& get(char &rch);

③ istream& get(char *pch, int nCount, char delim='\n');

④ ostream& put(char ch);

(4) Similarities and differences between text files and binary files 

4. Random access to files

(1) Functions related to location pointers in class istream

① Move read pointer function

② A function that returns the current position of the write pointer

(2) Functions related to location pointers in class ostream 

① Move and write pointer function

② A function that returns the current position of the write pointer




1. Basic concepts of files and file stream classes

Looking at files from different angles leads to different file classifications:
  • According to the encoding method of file data, it is divided into: text file and binary file
  • According to different access methods , it is divided into: sequential access files and random access files
The so-called "text files" and "binary files" are classified from the perspective of file formats, which are conventional classifications from the perspective of computer users.

(1) The concept of files 

⚫The so-called "sequential access files" and "random access files" are divided according to the way of accessing the data in the files.
  • Sequential access to files : It is to perform sequential operations according to the order of data storage in the file. In order to access the i-th data, the i-1-th data must be accessed first. During the entire file operation process, the work of moving the position pointer is handed over to the system. automatic completion.
  • Tape file : It is a typical sequential access file.
  • Random access file : According to the needs of the application, the position pointer can be moved directly to the required position in the file by command and perform data operation.
⚫The basic operations on files are divided into reading files and writing files .
  • Read file : It is to read the data in the file into the memory, also called "input".
  • Write file : It is to store the data in the memory into the file, also called "output".

(2) C++ file stream class 

1. There are 3 stream classes in the C++ standard class library that can be used for file operations. These 3 classes are collectively called file stream classes, and they are as follows:
  • ifstream: used to read data from a file.
  • ofstream: used to write data to the file.
  • fstream: It can be used to read data from files and write data to files.
2. When using these three stream classes,  the fstream  header file needs to be included in the program.
  • Both class ifstream and class fstream are derived from class istream, so class ifstream has all the member functions of class istream.
  • Similarly, class ofstream and class fstream also have all member functions of class ostream.
  • There are some very familiar member functions in these three classes, such as operator<<, operator>>, peek(), ignore(), getline(), get(), etc.
3. In a program, to use a file, there must be 3 basic steps:
  • Open (open) the file - operate the file - close (close) the file.
  • To operate a file is to read/write the file.

4. The C++ file stream class has corresponding member functions to implement file operations such as opening, reading, writing, and closing.



2. Open and close files

There are two ways to open a file:
1. Create a stream object first, and then call the open() function to connect to an external file. The format is as follows:
流类名 对象名;
对象名.open(文件名,模式);
2. Call the constructor of the stream class with parameters, and connect to the external file while creating the stream object. The format is as follows:
流类名 对象名(文件名,模式);
  • The "stream class" is the file stream class ifstream, ofstream or fstream defined by the C++ stream class library.
  • If the file is opened for reading , the class ifstream should be used 
  • If the file is opened for writing , the class ofstream should be used 
  • If the file is opened for reading/writing, the class fstream should be used 

(1) Open the file 

schema markup Suitable effect
ios::in ifstream
fstream
Open the file for reading.
Error opening if file does not exist
ios::out ofstream
fstream
Open the file for writing.
If the file does not exist, create a new file;
if the file already exists, delete the original content when opening
ios::app ofstream Open the file for appending, which is used to add data to the end of the file.
If the file does not exist, create it
ios::ate ofstream Open an existing file and set the file read pointer to the end of the file.
Error opening if file does not exist
ios::trunk ofstream Delete the existing contents of the file. Same as ios::out when used alone
ios::binary ifstream
ofstream
fstream
Open the file in binary mode.
If this mode is not specified, the file will be opened in the default text mode
ios::in | ios::out fstream Open an existing file, both for reading its content and writing data to it. When the file is first opened, the original content remains unchanged.
Error opening if file does not exist
ios::in | ios::out ofstream Open an existing file so that data can be written to it.
When the file is first opened, the original content remains unchanged.
Error opening if file does not exist
ios::in | ios::out | ios::trunc fstream Opens a file for both reading its contents and writing data to it.
If the file already exists, clear the original content when opening;
if the file does not exist, create a new file

[Example 1] Open an input file stream object and read the file content in read mode

ifstream inFile; //建立输入文件流对象
inFile.open("data.txt",ios::in); //连接文件,指定打开模式
// 也可以使用第二种方式打开,语句如下:
ifstream inFile("data.txt",ios::in);

[Sample code]  To read data from a file named data.txt in the current folder, you can use the following statement to open the file:

#include <fstream>    // 包含文件流头文件
#include <iostream>
using namespace std;

int main() {
    ifstream inFile;  // 定义输入文件流对象

    inFile.open("data.txt", ios::in);  // 打开名为 "data.txt" 的输入文件,以读模式打开

    if (!inFile) {  // 如果打开文件失败
        cerr << "Can't open file!" << endl; // 输出错误信息到标准错误流
        return 1;  // 返回 1,表示程序异常结束
    }

    // ... 在此处可以进行文件读取操作 ...

    inFile.close();  // 关闭输入文件流

    return 0;  // 正常结束程序
}

【Code Explanation】

  • It should be noted that when using file streams to read and write files, the opened file must be checked to ensure that the file is opened successfully. It is used here  if (!inFile) to check whether the file is opened successfully, which is equivalent to  if (inFile.fail()), the latter can check the status of the file stream.
  • In addition to input file streams, the C++ standard library also provides multiple file stream types such as output file streams, binary file streams, and memory file streams, which can meet the needs of reading and writing files in different situations. When performing file operations, you should follow the principle of safety and order, first open the file, perform necessary checks, then perform read and write operations, and finally close the file stream.
  1. #include <fstream>, importing the file stream header file.

  2. #include <iostream>, importing input and output stream header files.

  3. using namespace std;, using the standard namespace.

  4. int main() { , program entry.

  5. ifstream inFile;, declares an input file stream object  inFile.

  6. inFile.open("data.txt", ios::in);, opens the file named "data.txt" and opens the file stream in read mode. Multiple open options can be specified when opening a file. Commonly used options include  ios::in(read mode), ios::out(write mode), (binary mode), etc. These options can be combined ios::binaryby bitwise OR ( ) operations.|

  7. if (!inFile) { , if opening the file fails, execute the code block below.

  8. cerr << "Can't open file!" << endl;, which outputs an error message on the standard error stream  cerr indicating that opening the file failed.

  9. return 1;, the return result is 1, indicating that the program ends abnormally.

  10. inFile.close();, closes the input file stream.

  11. return 0;, the return result is 0, indicating that the program ends normally.

【Results of the】

  • This program has no specific execution results, it just opens a file named "data.txt", and opens the input file stream object in read mode  inFile. After that, the program can  inFile read the file through the object, if the reading fails, print an error message, and finally close the input file stream object.
  • It should be noted that since there is no specific file reading operation, this program just opens the file and goes through the process of judging the stream status, so the output of the program is no different from the standard output. If the "data.txt" file does not exist or other errors occur, the program will return 1, indicating that the program ended abnormally, otherwise the program will return 0, indicating that the program ended normally.
  • In addition, it should be noted that when performing a file read operation, you must first check whether the file is opened successfully to avoid invalid read or write operations. In this example, if opening the file fails, the program will output an error message to the standard error stream  cerr , indicating that the file failed to open.

[Example 2] Open an input file stream object and read the file content in the default read mode :

ifstream inFile; //建立输入文件流对象
inFile.open("data.txt"); //没有指定打开模式,默认以in方式打开文本文件

[Example code]  Call the constructor with parameters of the ifstream class, while creating the stream object, use the parameters to connect to the external file and specify the opening mode. To open a text file for reading, you can also use the following statement:

#include <fstream>   // 文件流头文件
#include <iostream>
using namespace std;

int main() {
    ifstream inFile;  // 建立输入文件流对象

    inFile.open("data.txt");  // 打开名为 "data.txt" 的输入文件,以默认读模式打开文件流

    if (!inFile) {   // 如果打开文件失败
        cerr << "Can't open file!" << endl;  // 输出错误信息到标准错误流
        return 1;    // 返回 1,表示程序异常结束
    }

    // ... 在此处可以进行文件读取操作 ...

    inFile.close();  // 关闭输入文件流

    return 0;  // 正常结束程序
}

【Code Explanation】

  • It should be noted that when using a file stream to read a file, the opened file must be checked to ensure that the file is opened successfully. It is used here  if (!inFile) to check whether the file is opened successfully, which is equivalent to checking  if (inFile.fail()) the status of the file stream.
  • When opening a file, you need to pay attention to selecting the file opening mode. Different modes can be used for reading and writing operations. Commonly used file opening modes include  ios::in(read mode), ios::out(write mode), ios::app(append mode), ios::trunc(truncation mode), ios::binary(binary mode )wait. When opening a file, if no open mode is specified, the input file stream object will open the file in read mode by default.
  1. #include <fstream>, importing the file stream header file.

  2. #include <iostream>, importing input and output stream header files.

  3. using namespace std;, using the standard namespace.

  4. int main() { , program entry.

  5. ifstream inFile;, declares an input file stream object  inFile.

  6. inFile.open("data.txt");, open the file named "data.txt", and open it in the default read mode. No open options are specified here, so the file stream object  inFile will use the default read mode  , which  has the same effect ios::inas if specified  .ios::in

  7. if (!inFile) { , if opening the file fails, execute the code block below.

  8. cerr << "Can't open file!" << endl;, which outputs an error message on the standard error stream  cerr indicating that opening the file failed.

  9. return 1;, the return result is 1, indicating that the program ends abnormally.

  10. inFile.close();, closes the input file stream.

  11. return 0;, the return result is 0, indicating that the program ends normally.

【Results of the】

  • This program has no specific execution results, it just opens a file named "data.txt", and opens the input file stream object in the default read mode  inFile. After that, the program can  inFile read the file through the object, if the reading fails, print an error message, and finally close the input file stream object.
  • It should be noted that since there is no specific file reading operation, this program just opens the file and goes through the process of judging the stream status, so the output of the program is no different from the standard output. If the "data.txt" file does not exist or other errors occur, the program will return 1, indicating that the program ended abnormally, otherwise the program will return 0, indicating that the program ended normally.
  • In addition, it should be noted that when performing a file read operation, you must first check whether the file is opened successfully to avoid invalid read or write operations. In this example, if opening the file fails, the program will output an error message to the standard error stream  cerr , indicating that the file failed to open.

[Example 3] Open an output file stream object and write the file content in output and binary mode

ofstream outFile; //建立输入文件流对象
outFile.open("c:\\c2019\\newfile",ios::out | ios::binary); //连接文件,指定打开模式
// 也可以使用如下语句打开文件:
ofstream outFile("c:\\c2019\\newfile",ios::out | ios::binary);

[Example code] To open (create) a binary file named newfile in the c2019 folder of the c drive to save the data generated by the program, you can use the following statement to open the file:

#include <fstream>   // 文件流头文件
#include <iostream>
using namespace std;

int main() {
    ofstream outFile;  // 建立输出文件流对象

    outFile.open("c:\\c2019\\newfile", ios::out | ios::binary);  // 打开名为 "c:\c2019\newfile" 的输出文件,以输出和二进制模式打开文件流

    if (!outFile) {   // 如果打开文件失败
        cerr << "Can't open file!" << endl;  // 输出错误信息到标准错误流
        return 1;    // 返回 1,表示程序异常结束
    }

    // ... 在此处可以进行文件写入操作 ...

    outFile.close();  // 关闭输出文件流

    return 0;  // 正常结束程序
}

【Code Explanation】

  • It should be noted that when using file stream to write to a file, the opened file must be checked to ensure that the file is opened successfully. It is used here  if (!outFile) to check whether the file is opened successfully, which is equivalent to  if (outFile.fail()), the latter can check the status of the file stream.
  • In addition to output file streams, the C++ standard library also provides various file stream types such as input file streams, binary file streams, and memory file streams, which can meet the needs of reading and writing files in different situations. When performing file operations, you should follow the principle of safety and order, first open the file, perform necessary checks, then perform read and write operations, and finally close the file stream.
  1. #include <fstream>, importing the file stream header file.

  2. #include <iostream>, importing input and output stream header files.

  3. using namespace std;, using the standard namespace.

  4. int main() { , program entry.

  5. ofstream outFile;, declares an output file stream object  outFile.

  6. outFile.open("c:\\c2019\\newfile", ios::out | ios::binary);, opens the file named "c:\c2019\newfile" and opens the file stream in output and binary modes. Multiple open options can be specified when opening a file. Commonly used options include  ios::in(read mode), ios::out(write mode), (binary mode), etc. These options can be combined ios::binaryby bitwise OR ( ) operations.|

  7. if (!outFile) { , if opening the file fails, execute the code block below.

  8. cerr << "Can't open file!" << endl;, which outputs an error message on the standard error stream  cerr indicating that opening the file failed.

  9. return 1;, the return result is 1, indicating that the program ends abnormally.

  10. outFile.close();, to close the output file stream object.

  11. return 0;, the return result is 0, indicating that the program ends normally.

【Results of the】

  • This program has no specific execution results, it just opens an output file named "c:\c2019\newfile", and opens the output file stream object in output and binary mode  outFile. Thereafter, the program can  outFile perform file writing operations through the object, and if the writing fails, an error message will be printed, and finally the output file stream object will be closed.
  • It should be noted that since there is no specific file writing operation, this program just opens the file and goes through the process of judging the stream status, so the output of the program is no different from the standard output. If the "c:\c2019\newfile" file does not exist or other errors occur, the program will return 1, indicating that the program ended abnormally, otherwise the program will return 0, indicating that the program ended normally.
  • In addition, it should be noted that when performing a file writing operation, you must first check whether the file is opened successfully to avoid invalid reading or writing operations. In this example, if opening the file fails, the program will output an error message to the standard error stream  cerr , indicating that the file failed to open. It should be noted that the data written in the binary file stream is stored in binary code, and the written data must be binary data, otherwise the written data may not be parsed correctly.

(2) Close the file 

Use the member function close()  in fstream  to close the file.

[Example] Use file stream to open, read and write files

【Example code】 

#include<iostream>   // 输入输出流头文件
#include<fstream>    // 文件流头文件
using namespace std;

int main()
{
    ifstream inFile("c:\\tmp\\test.txt", ios::in);  // 声明对象 inFile 并调用构造函数打开名为 "c:\tmp\test.txt" 的输入文件,以读取模式打开文件流

    if (inFile)  // 如果打开文件成功
    {
        cout << "成功打开文件: c:\\tmp\\test.txt\n";
        inFile.close();  // 关闭输入文件流
    }
    else
        cout << "打开文件失败: c:\\tmp\\test.txt\n";

    ofstream outFile("test1.txt", ios::out);  // 声明对象 outFile 并调用构造函数创建名为 "test1.txt" 的输出文件,以写入模式打开文件流

    if (!outFile)
        cout << "error1" << endl;
    else {
        cout << "成功打开文件: test1.txt\n";
        outFile.close();  // 关闭输出文件流
    }

    fstream outFile2("tmp\\test2.txt", ios::out | ios::in);  // 声明对象 outFile2 并调用构造函数创建名为 "tmp\\test2.txt" 的文件,以输入输出和写入模式打开文件流

    if (outFile2) {
        cout << "成功打开文件:tmp\\test2.txt\n";
        outFile2.close();  // 关闭文件流
    }
    else
        cout << "error2" << endl;

    return 0;  // 正常结束程序
}

【Code Explanation】

  • It should be noted that when using file streams for file operations, you must first check whether the file is opened successfully to avoid invalid read or write operations. In this example, the program uses different methods to create three file streams, and judges whether the file creation is successful by checking whether the file streams are opened successfully. Note that when creating a
  1. #include<iostream> And  #include<fstream> import input and output stream header files and file stream header files.

  2. using namespace std;, using the standard namespace.

  3. int main(), program entry.

  4. ifstream inFile("c:\\tmp\\test.txt", ios::in);, declare the object  inFile and call the constructor to open the input file named "c:\tmp\test.txt", open the file stream in read mode.

  5. if (inFile), if the file is opened successfully, execute the following block of code.

  6. cout << "成功打开文件: c:\\tmp\\test.txt\n";, output the prompt message of successfully opening the file.

  7. inFile.close();, closes the input file stream.

  8. else cout << "打开文件失败: c:\\tmp\\test.txt\n";, otherwise output a message indicating that the file failed to open.

  9. ofstream outFile("test1.txt", ios::out);, declare the object  outFile and call the constructor to create an output file named "test1.txt", opening the file stream in write mode.

  10. if (!outFile) cout << "error1" << endl;, if the creation of the file fails, an error message is output.

  11. else, otherwise execute the code block below.

  12. cout << "成功打开文件: test1.txt\n";, output the prompt message that the file is successfully created.

  13. outFile.close();, closes the output file stream.

  14. fstream outFile2("tmp\\test2.txt", ios::out | ios::in);, declare the object  outFile2 and call the constructor to create a file named "tmp\test2.txt", and open the file stream in input and output and writing modes.

  15. if (outFile2), if the file is successfully created, execute the following block of code.

  16. cout << "成功打开文件:tmp\\test2.txt\n";, output the prompt message that the file is successfully created.

  17. outFile2.close();, closes the file stream.

  18. else cout << "error2" << endl;, otherwise an error message is output.

  19. return 0;, end the program normally.

【Results of the】

1. If "c:\tmp\test.txt" exists and "tmp\test2.txt" does not exist, executing the above code will output the following results:

成功打开文件: c:\tmp\test.txt
成功打开文件: test1.txt
error2
  • Among them, the first line outputs the prompt message that the file "c:\tmp\test.txt" is successfully opened, indicating that the file is opened successfully, and the file stream is closed.
  • The second line outputs the prompt message that the file "test1.txt" is successfully created, indicating that the file is successfully created, and closes the output file stream.
  • The third line outputs the error message "error2", indicating that the attempt to open "tmp\test2.txt" failed, the file does not exist or failed to open.

2. If "c:\tmp\test.txt" does not exist, the first line will output the error message "Failed to open file: c:\tmp\test.txt", indicating that the file failed to open. Other output is independent of whether the file exists or was successfully opened.

3. It should be noted that since the program only opens the file and does not perform specific read and write operations, the output is no different from the standard output. In practical applications, it is necessary to perform specific read and write operations after the file is successfully opened, and close the file stream after the file operation is completed, otherwise the file may be damaged and cause problems in the program or system.



3. File read and write operations

(1) Read and write text files

[Example 1] Write the information entered by the user from the standard input to the text file "score.txt" in the form of a string

【Example code】 

  • Assume that a program is to be implemented now, and the student's student number, name and grade are input from the keyboard, and they are stored in the file score.txt.
  • You can use a text file to save the data, each row in the file saves a student's grade information, and the student
  • The data items of the grade information are separated by spaces, and the format is stored as follows: student number name grade
  • For the convenience of program implementation, it is assumed that the student ID does not exceed 10 bytes, the name does not exceed 20 bytes, and the grade is an integer
  • Input/output to/from the text file score.txt:
    #include <iostream>     // 输入输出流头文件
    #include <fstream>      // 文件流头文件
    using namespace std;
    
    int main()              // 主函数
    {
        char id[11], name[21];
        int score;
        ofstream outFile;   // 创建输出文件流对象
        outFile.open("score.txt", ios::out);    // 以写方式打开文本文件
        if (!outFile)       // 判断文件是否打开成功
        {
            cout << "创建文件失败" << endl;     // 文件打开失败
            return 0;       // 程序正常结束
        }
        cout << "请输入: 学号 姓名 成绩 (以Ctrl+Z结束输入)\n";
        while (cin >> id >> name >> score)      // 从标准输入读入数据
        {
            outFile << id << " " << name << " " << score << endl;    // 将数据写入文件流
        }
        outFile.close();    // 关闭输出文件流
        return 0;           // 程序正常结束
    }

【Code Explanation】

  • The main function of this program is to write the information entered by the user from the standard input line by line into the text file "score.txt". The program first creates an  ofstream object  outFileand uses  open() the function to open the text file, which is opened for writing. If the file fails to be opened, it will output a message indicating that the file creation failed, and return a value of 0, and the program ends. Otherwise, the program prompts the user to enter information, and then uses  while a loop to read information from the standard input stream  cin , store it in the defined variables  id, name and  score , and then write the data to the file stream. Loop until the end of input.
  • Finally, the call  outFile.close() closes the output file stream. This step is very critical, because the file stream must be closed before the program ends. This ensures that the data has been correctly written to the file.
  • It should be noted that before writing a file, it must be ensured that the file is successfully opened. Therefore, the program uses conditional judgment to ensure that the file is successfully created and opened before the file can be written.
  • In addition, the representation in the program  ios::out is opened in writing mode (while (cin >> id >> name >> score), and the original file content will be cleared at the same time), and it also  ios::app indicates that it is opened in appending writing mode, which also includes other options. For example,  ios::in it means to open at end of file in read mode.
  1. Use  #include the import  iostream and  fstream engine header files first.

  2. The main function  main() starts and defines three variables  id,  which are used to store the student number, name and grade read from the standard input stream name . score

  3. Declares a  ofstream type of object  outFilefor outputting data to a file.

  4. Use  outFile.open() the function to open the file "score.txt". The opening method is to open in writing mode, that is, if the file exists, the content of the file will be cleared, and if it does not exist, the file will be created. When opening a file, you need to specify the opening method, and the flag is used here  ios::out .

  5. Determine whether the file stream is opened successfully, if it fails to open, output an error message, end the program and return a value of 0; otherwise prompt the user to input, use a  while loop to read information from the standard input stream, and store it in a variable.

  6. Finally, write the read information  outFile << into the file stream  outFile , and add a newline at the end of the line. Loop until the end of input.

  7. Close the output file stream, freeing resources.

  8. The program ends normally.

【Results of the】

Since the program needs to read data from standard input, the data needs to be typed in manually and terminated with "Ctrl+Z". The input data should include student number, name and grade, each field is separated by a space.

  • For example, suppose the keyboard enters the following data:
    001 Alice 90
    002 Bob 85
    003 Charlie 78
    
  • Execute the program in the Windows command line window and output the following results:
    请输入: 学号 姓名 成绩 (以Ctrl+Z结束输入)    // 程序提示信息
    001 Alice 90                                 // 手动输入的数据
    002 Bob 85
    003 Charlie 78
    
  • After the data is input, the program detects the end of the input stream, automatically ends the input and starts writing the data to the file "score.txt". Since a carriage return is added after each information item is set, the data in the output file is also one line per line, formatted and arranged.
    001 Alice 90
    002 Bob 85
    003 Charlie 78
    
  • Finally, the program finishes running and exits normally.

[Example 2] Read student information from the file "score.txt" and output it to the screen

【Example code】 

  • Assume that a program is to be implemented now, and the student's student number, name and grade are input from the keyboard, and they are stored in the file score.txt.
  • You can use a text file to save the data, each row in the file saves a student's grade information, and the student
  • The data items of the grade information are separated by spaces, and the format is stored as follows: student number name grade
  • For the convenience of program implementation, it is assumed that the student ID does not exceed 10 bytes, the name does not exceed 20 bytes, and the grade is an integer
  • Input/output to/from the text file score.txt:
    #include <iostream>     // 输入输出流头文件
    #include <fstream>      // 文件流头文件
    #include <iomanip>      // 格式控制头文件
    using namespace std;
    
    int main()              // 主函数
    {
        char id[11], name[21];
        int score;
        ifstream inFile;    // 创建输入文件流对象
        inFile.open("score.txt", ios::in);   // 以读方式打开文本文件
        if (!inFile)        // 判断文件是否打开成功
        {
            cout << "打开文件失败" << endl;  // 文件打开失败
            return 0;       // 程序正常结束
        }
        cout << "学生学号 姓名\t\t\t成绩\n";    // 输出表头
        while (inFile >> id >> name >> score)   // 从文件中读取数据
        {
            // 格式化输出文件中的数据
            cout << left << setw(10) << id << " " << setw(20) << name << " " << setw(3) << right << score << endl;
        }
        inFile.close();     // 关闭输入文件流
        return 0;           // 程序正常结束
    }

【Code Explanation】

  • It should be noted that the program uses  iomanip the functions in the header file to control the output format and make the output more beautiful and tidy. Among them, setw() the width of the output data can be controlled, left and  right the alignment of the output string can be controlled.
  1. Introduced at the beginning  iostream, fstream and  iomanip three header files.

  2. int main() It is the main function, which defines three variables  id, name and  score are used to store student number, name and grade respectively.

  3. Creates an  ifstream object of type  inFile used to read information from a file.

  4. Use  inFile.open() the function to open the file "score.txt". The opening method is to open in read mode. If the file does not exist or an error occurs, NULL will be returned, that is, the opening fails.

  5. Determine whether the file stream is opened successfully, if it fails to open, output an error message, end the program and return a value of 0; otherwise output header information, the header has been formatted and controlled.

  6. Use  while a loop to read information from the file stream  inFile and store it in a variable.

  7. Finally, use  cout to achieve screen output, adopt formatted output mode, use  setw() and  left, right control output width and alignment. Loop until the end of the file is read.

  8. Close the input file stream, freeing resources.

  9. The program ends normally.

【Results of the】

  • Assuming that the input is entered in the Windows command line window, the input needs to be input line by line and terminated with the Enter key. The keyboard input content:
2018001001 zhangsan                90
2018001002 lisi                     9
2018001003 wangwu                  85
2018001004 zhangsanfeng           100
2008001005 zhouwuzhengwangyishi   100
  • The following is the output of the program:
学生学号    姓名                   成绩
2018001001 zhangsan                90
2018001002 lisi                     9
2018001003 wangwu                  85
2018001004 zhangsanfeng           100
2008001005 zhouwuzhengwangyishi   100
  • The program first outputs a row of headers, and then reads each row of student information from the file in turn. Since  leftright and  setw() adjust the output width and alignment, each line of output information will occupy a fixed width while maintaining left or right alignment, making the overall structure of the output more readable.
  • It should be noted that if the format of the input file is wrong, for example, the information items are not separated by spaces as required, the program cannot read the information items correctly. In addition, if the length of the input information cannot be guaranteed to meet the requirements, for example, the student number has only 8 characters, or the name exceeds 20 characters, the output information may be unbalanced, and the output width needs to be readjusted.

[Example 3] From the file name input by the user (the default is the file in the current directory), read the content of the file by line, and output the line number at the beginning of each line

【Example code】

#include <iostream>     // 输入输出流头文件
#include <fstream>      // 文件流头文件
#include <iomanip>      // 格式控制头文件
using namespace std;

int main()              // 主函数
{
    char ch, filename[20];
    int count = 0;      // 行号计数器
    bool newline = true; // 开始一个新行的标志

    cout << "请输入文件名: ";
    cin >> filename;
    ifstream inFile(filename, ios::in);    // 以读方式打开文本文件
    if (!inFile)        // 判断文件是否打开成功
    {
        cout << "打开文件失败" << endl;  // 文件打开失败
        return 0;       // 程序正常结束
    }
    while ((ch = inFile.get()) != EOF)    // 从文件中读取每个字符
    {
        if (newline)    // 若是新行开始,则显示行号
        {
            cout << setw(4) << ++count << ": ";    // 输出行号并格式化对齐
            newline = false;    // 清除新行标志
        }
        if (ch == '\n') // 若为换行符,则表示将开始一个新行
            newline = true;     // 设置新行标志
        cout << ch;     // 输出字符
    }
    inFile.close();     // 关闭文件
    return 0;           // 程序正常结束
}

【Code Explanation】

  • Note that the program assumes that each line in the input file is terminated by a carriage return and line feed. In addition, the line number part is used  setw() for alignment control to ensure that the line number is displayed with a fixed column width, which is convenient for users to view.
  • In addition, the program does not detect that the file name contains illegal characters or the file does not exist, so if the user enters an illegal file name or accesses a file that does not exist, the program will throw an exception, which affects the stability of the program will have an impact.
  • In addition, it should be noted that since the program reads the contents of the file line by line, if the length of a line exceeds the maximum length specified by the program, the program may end abnormally. In order to avoid this situation, you can increase the limit on the number of characters in each line, or use technologies such as dynamic memory allocation to dynamically allocate enough memory space at runtime to read the entire file correctly.
  1. Introduced at the beginning  iostream, fstream and  iomanip three header files.

  2. int main() It is the main function, which defines three variables  ch, count and  newline, which are used to store the read characters, count the line number and judge whether it is a new line.

  3. Output a prompt message asking the user to type a file name. The file entered by the user is then opened using  ifstream an object of type  inFile Open for reading. Returns NULL if the file does not exist, that is, the open failed.

  4. Determine whether the file stream is opened successfully. If the opening fails, an error message is output, the program ends and a value of 0 is returned; otherwise, a read operation is performed to read each character from the file.

  5. If a new line is encountered, it is  setw() formatted with , and the line number is output and aligned. Then clear the flag to indicate not on a new line.

  6. If a newline character is encountered, the newline flag is set to record where the next character is on a newline.

  7. cout Output characters are used whenever possible  .

  8. Will be  inFile closed to release resources.

  9. The program ends normally.

【Results of the】

  • It is known to use the returned result of Example 2 as data
    2018001001 zhangsan                90
    2018001002 lisi                     9
    2018001003 wangwu                  85
    2018001004 zhangsanfeng           100
    2008001005 zhouwuzhengwangyishi   100
    
  • Keyboard input file name "score.txt"
    score.txt
  • The program reads each line from the file and prints the line number at the beginning of each line. The following is the output of the program:
    请输入文件名: score.txt
    1: 2018001001 zhangsan                90
    2: 2018001002 lisi                     9
    3: 2018001003 wangwu                  85
    4: 2018001004 zhangsanfeng           100
    5: 2008001005 zhouwuzhengwangyishi   100
    
  • It can be seen that the output results are output in ascending order of line numbers, and each line starts with a line number. setw() And the formatting alignment is used between the line number and the line content  , so that the output of each line has the same format and width.
  • It should be noted that if the file name is entered incorrectly or the file does not exist, the program will output a "failed to open the file" message and end the program. In addition, the program needs to ensure that each line of input ends with a carriage return and a line feed, otherwise it may cause incomplete content read by the program. When using this program, you must ensure that the input file can correctly read the content of each line, and the content of each line conforms to the expected format of the program.

(2) Read and write binary files 

  • Reading and writing binary files cannot use the aforementioned methods similar to cin and cout to read and write data from streams.
  • C++ opens the binary file in binary mode, calls the read() member function of ifstream or fstream to read data from the file, and calls the write() member function of ofstream or fstream to write data to the file.

①Use  the ostream::write() member function to write the file

The write() member function of ofstream and fstream inherits from the ostream class, and the prototype is as follows:
ostream & write(char * buffer, int nCount);
  • This member function writes the contents of nCount bytes pointed to by the buffer in the memory to the file, and the return value is a reference to the object on which the function acts, such as the return value of obj.write(...) is a reference to obj.
  • This function is a non-formatting operation, and directly stores the data pointed by the buffer into the file in byte sequence.
  • When using write() and read() to read and write data, there is no need to "insert" additional separators between the data, because they both require the second parameter to specify the length of reading and writing.

[Example] Use a custom CStudent class to input student information from the console and write it into a binary file

【Example code】 

#include <iostream>     // 输入输出流头文件
#include <fstream>      // 文件流头文件
using namespace std;

class CStudent      // 自定义学生类
{
public:
    char id[11];        // 学号
    char name[21];      // 姓名
    int score;          // 成绩
};

int main()              // 主函数
{ 
    CStudent stu;       // 学生类对象
    ofstream outFile("students.dat", ios::out | ios::binary);  // 以二进制写方式打开文本文件
    if (!outFile)       // 判断文件是否打开成功
    {
        cout << "创建文件失败" << endl;    // 创建失败
        return 0;       // 程序结束并返回值 0
    }
    cout << "请输入: 学号 姓名 成绩 (以Ctrl+Z结束输入)\n";
    while (cin >> stu.id >> stu.name >> stu.score)    // 输入学生信息
        outFile.write((char*)&stu, sizeof(stu));      // 向文件中写入学生信息
    outFile.close();    // 关闭文件
    return 0;           // 程序结束
}

【Code Explanation】

  • It should be noted that since this program deals with binary files, when entering student information, it is necessary to ensure that each student's information conforms to the expected format of the program, and the number of bytes of each student's information is the same. Otherwise, it may cause the program to read errors, parse errors, or output wrong information. When using this program, be sure to ensure that each student information entered meets the specification requirements and uses the correct input format.
  1. Introduced at the beginning  iostream and  fstream two header files.

  2. class CStudent A custom student class is defined, which contains each student's student number, name and grade information, and is used to record student information.

  3.  A student object  main() of type is defined in  the main function  , and   a binary file named "students.dat" is opened with  the object of type  and opened for writing. If the file fails to open, the program outputs an error message, and the program ends with a return value of 0.CStudentstuofstreamoutFile

  4. The program outputs a prompt message, requiring the user to enter the student's student number, name and grade. If the user inputs student information, write the student information into the file, otherwise end the input process.

  5. Use to  outFile.write() write the current input student information to the file sizeof(stu) to calculate the number of bytes occupied by a single student information.

  6. Start the next round of input operations until the user finishes typing.

  7. Close the file to free resources.

  8. The program ends normally.

【Results of the】

  •  Suppose the keyboard enters the following content and ends with Ctrl+Z:
    2019001001 ZhangSan 90
    2019001002 LiSi 100
    2019001003 WangWu 78
  • According to the input content, the program will enter the information of three students, which are student number, name and grade. The following is the execution result of the program:
    请输入: 学号 姓名 成绩 (以Ctrl+Z结束输入)
    2019001001 ZhangSan 90
    2019001002 LiSi 100
    2019001003 WangWu 78
    ^Z
  • It can be seen that the program prompts the user to enter student information, one student information per line, each student information includes student number, name and grade, separated by spaces.
  • Since the entered information is in the format expected by the program, the program can write the information to the binary file "students.dat" normally.

②Use  the istream::read() member function to read the file

The member function read() of ifstream and fstream actually inherits from the class istream, and the prototype is as follows:
istream &read(char * buffer, int nCount);
  • This member function reads the content of nCount bytes from the file and stores it in the memory buffer pointed to by buffer. The return value is a reference to the object that the function acts on.
  • This function is a non-formatting operation, which does not process the read byte sequence, but directly stores it in the buffer, and is interpreted by the type definition of the program. 

③Use  the ostream::gcount() member function to get the number of read bytes

  • If you want to know how many bytes are successfully read in each read operation, you can call the member function gcount( ) of the file stream object immediately after the read() function is executed, and the return value is the number of bytes successfully read in the latest read() function execution. The number of bytes fetched.
  • The gcount() member function prototype is as follows:
    int gcount( );

(3) Use member functions put() and get() to read and write files

The member functions get() and put() are often used to read and write characters or text files, but they can not only be used to process characters, but also can effectively process binary files. 

The function get() has 3 main forms:

int get( );
istream& get(char &rch);

istream& get(char *pch, int nCount, char delim=’\n’);

The syntax of the function put() is as follows:

ostream& put(char ch);

① int get();

  • The get() function without parameters extracts a character (including blank characters) from the specified input stream, and the return value of the function is that character.
  • When an end-of-file character is encountered, the system constant EOF is returned.

② istream& get(char &rch);

  • Extracts a character (including whitespace) from the specified input stream, making that character the object referenced by rch.
  • When the end-of-file character is encountered, the function returns 0; otherwise, it returns a reference to the istream object.

③ istream& get(char *pch, int nCount, char delim='\n');

  • Reads nCount-1 characters from the stream's current character, or ends at the specified delimiter delim.
  • The function writes the read characters (excluding the delimiter) into the array pch, and adds the terminator '\0' after the string.

④ ostream& put(char ch);

The function of the function is to insert a byte into the output stream.

(4) Similarities and differences between text files and binary files 

During the input/output process, the system needs to compare the data format of the internal and external memory. Text files store data in text form
  • Its advantage is that it has high compatibility
  • The disadvantage is that when storing a batch of pure numerical information, it is necessary to artificially add separators between the data
  • should be converted
  • Another disadvantage of text files is that they do not facilitate random access to data
Binary files store data in binary form
  • Its advantage is that it facilitates random access to data (data of the same data type occupy the same size, and there is no need to artificially add separators between data)
  • During the input/output process, the system does not require any transformation of the data
  • The disadvantage is poor data compatibility
⚫Usually plain text information (such as character strings) is stored in the form of text files, while numerical information is stored in the form of binary files.


4. Random access to files

⚫ If a file can only perform sequential access operations, it is called a sequential file.

  • Typical sequential files (devices) are keyboards, monitors, and files saved on magnetic tape.
  • If a file can be accessed anywhere in the file, it is called a random file.
  • Disk files are typical random files.
⚫In the process of accessing files, if the files are accessed strictly according to the order in which the data is stored from beginning to end, it is called sequential access.
⚫In the process of accessing a file, if it is not necessary to access the file in the order in which the data is stored, but to access it at different locations in the file according to the needs, it is called random access.
Obviously, only sequential access can be performed for sequential files; both sequential and random access can be performed for random files.

(1) Functions related to location pointers in class istream

① Move read pointer function

istream & seekg(long pos);
  • The function of this function is to set the read pointer to pos , that is, to move the read pointer to the pos byte of the file.
istream & seekg(long offset, ios::seek_dir dir);
  • The function of this function is to move the read pointer by offset bytes according to the indication (direction) of seek_dir, where seek_dir is an enumeration type defined in class ios.
enum seek_dir {beg=0, cur, end};

The constant values ​​of seek_dir have the following meanings:

  • ios::beg: Indicates the start position of the stream. In this case, offset should be a non-negative integer.
  • ios::cur: Indicates the current position of the stream. At this time, if offset is a positive number, it means moving backward (end of file), which is
  • Negative numbers move forward (head of file).
  • ios::end: Indicates the end position of the stream. In this case, offset should be a non-positive integer.

② A function that returns the current position of the write pointer

long tellg( );
  • The return value of the function is the current position of the read pointer in the stream.

(2) Functions related to location pointers in class ostream 

① Move and write pointer function

ostream & seekp(long pos);
  • The function of this function is to set the write pointer to pos , that is, to move the write pointer to the pos byte of the file.
ostream & seekp(long offset, ios::seek_dir dir);
  • The function of this function is to move the write pointer by offset bytes in the direction indicated by seek_dir.

② A function that returns the current position of the write pointer

long tellp( );
  • The return value of the function is the current position of the write pointer in the stream.
  • Note: In the class fstream, it not only provides the functions seekg() and tellg() to operate the read pointer, but also provides the functions seekp() and tellp() to operate the write pointer. In fact, these two pointers are the same pointer in the file .

Guess you like

Origin blog.csdn.net/qq_39720249/article/details/131401027