Files in cpp tutorial

A Comprehensive Guide on File Handling in C++

Hello World! You have been working with data in the program and struggling with saving its states across multiple restarts. Yeah, I know that is temporary and will be gone as the program exists. In this post, I will teach you how you can use C++ file handling and save not only text data into it but also binary data like Class or Struct. You can clone the repository for all the snippets and source code used in this tutorial https://github.com/tbhaxor/cpp-file-handling-tutorial.

Table of Contents

  1. Why do you need File Handling Anyway?
  2. Getting Started with File Handling
    • Text File vs Binary File
    • What is EOF
  3. Writing into the File
  4. Reading from the File
    • Reading until line end (EOL)
  5. Check Whether the File is Open or Not
  6. Closing file handle
  7. Appending into the Existing File
  8. Storing Class Object in the File
  9. Using I/O Streams of the File
    • Read/Write Cursors

Why do you need File Handling Anyway?

The program state gets vanished when it is exited or the functions go out of scope during execution. Sometimes it’s required to have the states for future execution.

Читайте также:  Получить страницу html css

Take the example of a game, you don’t play it continuously. Saving the same and loading it later is very basic. I had first seen this in the Project IGI game and then Age of Empires. Nowadays multiplayer games are getting popular and they use databases to store this information.

That’s a great idea to use databases. So why not use the database, it can be shared easily. Let me tell you that there is no different magic going on there, DBMS uses files to store the data. So it boils down to file handling.

Getting Started with File Handling

There are and will be 2 types of operation in the file: Read file will allow you to retrieve the content and write file will allow you to put the content into the file using the current stream. A stream is basically a channel that carries your data from/to the file.

std::ifstream class is used to open the file in reading mode and std::ofstream is used to open the file in the write mode.

These classes provide different methods and properties as an abstraction to deal with files, or I would say even the large files.

Text File vs Binary File

There are two types of files: Human readable (or text) and human non-readable (binary).

It is easy to determine whether a file is a text or binary: If you open a file in a text editor (let’s assume notepad or vscode), it will show all the characters and you can pronounce them. They might or might not make sense, but it’s not required here. This file is a text file. If you are unable to pronounce any character, then that file is a binary file.

Note A binary file can contain a few readable characters as well, and that is ok.

Text File Binary File
Text File Binary File

What is EOF

std::cout  ifile->bad()  " "  ifile->eof()  " "  ifile->fail(); // 0 1 1 

Writing into the File

Enough talking, let’s start by writing a text content into the file using std::ofstream . Before all of that, you need to instantiate the ofstream and open the file:

std::ofstream *file = new std::ofstream(); file->open("file.txt", std::ios::out); 

The .open() function, as it says, open the file with name (first argument) and the mode (second argument). I will discuss different modes with you as we proceed, std::ios::out mode is used to tell the function, that opens the file in write mode, overwrite the contents of it if it exists or create a new one. Now it’s time to write into the file stream using the left shift operator

(*file)  "Hello World"  std::endl; 

Since we are using a pointer variable, therefore it is required to dereference the file handle to access the

Reading from the File

std::ifstream *file = new std::ifstream(); file->open(argv[1], std::ios::in); 
std::string data; (*file) >> data; std::cout  data  std::endl; // Hello\n 

Reading until line end (eol)

std::getline(*file, data); std::cout  data  std::endl; // Hello World\n 

Check Whether the File is Open or Not

Till now we are believing that the file exists and is ready for any I/O operation, but what if the condition is otherwise? What if it failed to open? Will it throw an error? The answer to the question is, NO. It will not throw error but the RW will not work. You can use std::ifstream::is_open() or std::ofstream::is_open() . The functions returns boolean value, so if the file is actually opened successfully, it will return true.

if (file->is_open())  // do the rest actions here > else  std::cout  <"Unable to open file\n"; > 

Closing file handle

When you are done with the file operations, it is recommended to close the file handle which will dispose of the file stream after writing any pending sequence of characters and clearing the buffer for both input and output streams. For this you can use std::ofstream::close() or std::ifstream::close .

Appending into the Existing File

What if you want to append the data into the file without losing old content. In the ios::out , it overwrites the file and reading the content of files, appending in memory and then writing to a file doesn’t seem to be a space and time-efficient solution. There is another mode of opening the file that you can use in place of ios::out , which is append mode ios::app . This will allow you to write from the end of the file to the size of the data. When you choose to open the file with append mode, the put cursor of the handle is set at the end of the file.

Storing Class Object in the File

So far you have seen me dealing with the text file, but in the real world, there are more than binary files with the custom format, like Zip archives, PDF files and other document files. To open the file in binary mode, you need to specify std::ios::binary mode in the open() method of std::ifstream or std::ofstream .

in_file->open("file.bin", std::ios::binary | std::ios::in); out_file->open("file.bin", std::ios::binary | std::ios::out); 

For reading and writing, you must use std::ifstream::read() and std::ofstream::write() because the binary file saves the raw bytes and does not perform any kind of formatting. With this, you can now store the object of structs or classes directly into the file without serializing it into the textual format. It will be then automatically deserialized when the file is read. Let’s create a simple class called Student that will have name and age fields and a whoami() method to return a std::string object.

class Student  private: std::string name; unsigned short age; public: Student()  this->name = "" this->age = 0; > Student(const char * name, unsigned short age)  this->name = std::string(name); this->age = age; > std::string whoami() const  std::stringstream s; s  <"I am "  <this->name  <" and "  <this->age  <" years old"; return s.str(); > >; Student student("Gurkirat Singh", 20); 

You can save this to a file using the following snippet by casing it to char* because of its definition in the stdc++. read more

out_file->write(reinterpret_castchar*>&student, sizeof(student)); 

Once this is successfully saved into the file, you will verify that there are some weird characters present in the file and that is normal, because the string data also stores the information of deserializing the object.

Student mystudent; in_file->read(reinterpret_castchar*>&mystudent, sizeof(mystudent)); std::cout  <mystudent.whoami()  <std::endl; // I am Gurkirat Singh and 20 years old 

Now as a beginner, you must be thinking that the Student type is different from the char type. So why does the casting pointer not affect serialization? I would like to tell you that, you are getting confused between pointer type and other data types. For any data type, the pointer type would be 8 bytes or 4 bytes based on the CPU architecture, because it stores the starting address of the memory where that actual data of a type is stored. If the type of data is char, then it will consume 1 byte in the memory otherwise sizeof(T) .

Using I/O Streams of the File

It is not like you can open a file only in one mode (that is either read or write), using std::fstream you can perform both input/output operations on the file with the same file handle.

Read/Write Cursors

  • std::ios::beg — from the beginning of file
  • std::ios::cur — from the current position of the cursor
  • std::ios::end — from the ending of the file or where the reader hits EOF

Note You must clear the flags using std::fstream::clear() to clear all the error bits before using seekg() or seekp() . read more

Источник

C++ Files

To use the fstream library, include both the standard AND the header file:

Example

There are three classes included in the fstream library, which are used to create, write or read files:

Class Description
ofstream Creates and writes to files
ifstream Reads from files
fstream A combination of ofstream and ifstream: creates, reads, and writes to files

Create and Write To a File

To create a file, use either the ofstream or fstream class, and specify the name of the file.

To write to the file, use the insertion operator (

Example

int main() // Create and open a text file
ofstream MyFile(«filename.txt»);

// Close the file
MyFile.close();
>

Why do we close the file?

It is considered good practice, and it can clean up unnecessary memory space.

Read a File

To read from a file, use either the ifstream or fstream class, and the name of the file.

Note that we also use a while loop together with the getline() function (which belongs to the ifstream class) to read the file line by line, and to print the content of the file:

Example

// Create a text string, which is used to output the text file
string myText;

// Read from the text file
ifstream MyReadFile(«filename.txt»);

// Use a while loop together with the getline() function to read the file line by line
while (getline (MyReadFile, myText)) // Output the text from the file
cout >

// Close the file
MyReadFile.close();

Источник

Оцените статью