10 - Files
10 - Files
🔨 🔥 Assignment 🔥 🔨
Create a new project in the way explained in the first instruction.
Text files in C++
C++ can handle files using mechanism called file streams. In order to use them, we need to include the <fstream>
library:
#include <fstream>
Similarly to FILE pointer in C, we have std::fstream
:
std::fstream file;
To open a file, we can use method open:
void std::fstream::open(std::string filename, std::ios_base::openmode mode);
Available modes:
std::ios::app
- append. Opens file for writing, new data is written at the end.std::ios::ate
- at end. Opens file and sets current pointer to the end.std::ios::in
- input. Allows to read data from filestd::ios::out
- output. Allows to write to filestd::ios::trunc
- truncate. Clears the file while opening an existing file.
Example - opening file “test.txt” for reading and writing (it is possible to join modes with character |
):
std::fstream file;
"test.txt", std::ios::in | std::ios::out); file.open(
To check if the file was correctly opened you can use functions is_open()
or good()
, which return true or false:
std::fstream file;
"test.txt", std::ios::in | std::ios::out);
file.open(if (file.is_open()) {
std::cout << "File was correctly opened!" << std::endl;
}
To close a file, we can use close()
method:
file.close();
In case of C++ fstreams
it is possible to read from them in a similar way to the reading with std::cin
:
char letter;
double number;
file >> letter >> number;
or write back to the file:
char letter = 'A';
1.23456; file << letter <<
It is also possible to read a whole line with getline()
:
std::string line;
std::getline(file, line);
To read all of the information in the file, it is possible to write a loop and check if we reached the end of the file with eof()
method:
while(!file.eof()) {
int number;
file >> number; }
or when using getline()
:
std::string line;
while(std::getline(file, line)) {
//process a single line
}
ATTENTION In C++, we can create a default reading stream by using ifstream
(instead of fstream
) or a default writing stream by using ofstream
(instead of fstream
). Example:
std::ifstream file; // Default reading stream
"name.txt"); file.open(
🔨 🔥 Assignment 🔥 🔨
Using a plain text editor such as Notepad, Notepad++ or Visual Studio Code create a simple text file and fill it with some words (texts) separated by spaces. Open the file in your program and print each word in a separate line on the screen.
Read the same file, but store the words in a variable (eg. using
std::vector
) and then write it to the new file but in reverse order.
Example original file:
aaa bbb ccc
Example output file:
ccc bbb aaa
Close and open the output file once again. Append a single line to the end, but do not clear the previously written data.
Read the data about students from the file under the LINK. Store the information about the students in the
std::vector
of prepared structures. Then:- print the content,
- ask user for a new student info, add as many students as the user wants to,
- ask user which students should be removed (by providing their last name), remove as many students the user wants to,
- sort all students based on their grade (from lowest to highest),
- save all data to a new file in the same format.
Text files vs binary files
In text files the information is stored as characters as in case of binary files the information is stored directly as an information in the memory. Let’s consider an example in which we would only write the Pi number (3.14159265359) into text and binary files. Now let’s see both files in the text editor (like notepad++):
- text file:
3.14159
- binary file:
ę.DTű! @
For the text file, each digit of the number was converted to the character and then written to the file. If we would need to read the number back to the program, we would lose some precision as the number we stored has only 5 digits after decimal point. In case of a binary file, the number is written to the file as a sequence of bytes. Therefore, even if not easily readable by humans, the number is stored with greater precision.
What happens when we try to store text in a file. Let’s try to write Programming class to text and binary files:
- text file:
Programming class
- binary file:
Programming class
In case of characters, the sequence of bytes directly corresponds to the visual characters, which results in the same files for text and binary files.
The binary files are faster than text files as you don’t need to translate each byte to character. But it is necessary to remember that the representation in the memory depends on the compiler (the size of the type in a memory) and on the architecture of the CPU (little endian or big endian). Therefore, reading the same file on different computers might provide different results or even fail.
Moving inside file in C++
Sometimes, it is necessary to read the file again or just move from the current position in a file. To do this, we can use:
std::istream::seekg (streamoff off, ios_base::seekdir way); // For reading files
istream& std::iotream::seekp (streamoff off, ios_base::seekdir way); // For writing files ostream&
where off means the offset and way specifies the relation of this offset. Way can have the following values:
std::ios::beg
- beginning of the streamstd::ios::cur
- current position in the streamstd::ios::end
- end of the stream
Therefore, setting the off to 1 and way to std::ios::beg
means that we move our position in a file to 1 with respect to the beginning. The example:
std::ofstream file;
0, std::ios::beg); // Moves to the beginning
file.seekp(0, std::ios::end); // Moves to the end file.seekp(
Finding element separators in lines
In many cases the data in a text file is not separated by spaces (
), but other, special ASCII characters. Eg. in case of CSV (Comma Separated Values), a comma (,
) is the separating character. find()
LINK and substr()
LINK methods of std::string
can be used to extract elements in lines:
std::string line = "John;Important;London"; // single line read from file
size_t pos; // variable for storing separator position, size_t is simply an integer type
';'); // find position of first spearator
pos = line.find(std::string name = line.substr(0, pos); // copy of a substring from position 0 to pos
1, line.length()); // assign line with a substring without first element
line = line.substr(pos+
';');
pos = line.find(std::string surname = line.substr(0, pos);
std::string city = line.substr(pos+1); // remaining, last element
This procedure can be looped if needed, or modified to handle unknown number of elements, as find()
method will return std::string::npos
if the specified character is not found.
Converting std::string
to numerical values
In order to convert characters in std::string
into numerical variables following functions can be used:
- std::stoi -
std::string
toint
, - std::stod -
std::string
todouble
, - std::stof -
std::string
tofloat
.
std::string s1 = "1234";
int i1 = std::stoi(s1);
std::cout << i1 + 1000 << std::endl;
std::string s2 = "250 km/h";
int i2 = std::stoi(s2);
std::cout << i2 << std::endl;
std::string s3 = "1.434";
double d1 = std::stod(s3);
std::cout << d1 << std::endl;
2234
250
1.434
Final assignments 🔥 🔨
Exercise 1
Read a file containing information about the fastest cars: LINK. Create functions that answer following questions:
- How many cars are faster than 300 km/h?
- Which car was the first to cross the 300 km/h? What year was it?
- Sort the file based on the car name and save to file cars_sorted.txt
- Print all of the information about the fastest car on the list
Exercise 2
Read a file containing the list of countries that produce the most oil: LINK created based on WIKI. The first column contains country name and information if the country belongs to OPEC group. The second column informs about the number of barrels created daily. Do the following tasks:
- Read the information and print it to the screen
- Create a function that will print only the information about the OPEC countries. When printing, remove the (OPEC) next to the country name.
- Sort information based on oil production. Print information about top 10 countries. How many of them belong to OPEC?
- For top20, what is the total production of OPEC countries? And what is the production of non-OPEC countires?
- How many countries produce more than 1000 barrels per minute?
Homework đź’Ą đźŹ
You are responsible for processing the information about the demography in Poland provided in a file (LINK). The first line informs about the content of the file: the first column is the name of the voivodeship, then we have number of men living in cities, number of women living in cities, number of men living in villages and the number of women living in villages. Please allow user to perform following tasks that should be chosen from the menu (the program ends when x or X is read):
- Read the data using the file handling in C++
- Save the data to another file using the file handling
- Print all currently stored information to the screen
- Print information about the voivodeship with the greatest number of people living in it
- Sort the information according to the ratio of the number of people living in cities to the number of people living in villages
- Remove information about voivodeships that have more women than men
Authors: Michał Nowicki, Jan Wietrzykowski, Dominik Pieczyński, Tomasz Mańkowski