Home | Projects | Notes > C++ Programming > I/O & Streams
Streams and I/O
Stream manipulators
Reading and writing to a text file
Using string streams
C++ uses streams as an interface between the program, and input/output devices.
Independent of the actual device
Sequence of bytes
Input stream provides data to the program
Output stream receives data from the program
Header File | Description |
---|---|
iostream | Provides definitions for formatted input and output from/to streams |
fstream | Provides definitions for formatted input and output from/to FILE streams |
iomanip | Provides definitions for manipulators used to format stream I/O |
Class | Description |
---|---|
ios | Provides basic support for formatted and unformatted I/O operations (Base class for most other classes) |
ifstream | Provides for high-level input operations on file based streams |
ofstream | Provides for high-level output operations on file based streams |
fstream | Provides for high-level I/O operations on file based streams (Derived from ofstream and ifstream ) |
stringstream | Provides for high-level I/O operations on memory based strings (Derived from istringstream and ostringstream ) |
Global objects - Initialized before main executes
Best practice is to use cerr
for error messages and clog
for log messages.
Object | Description |
---|---|
cin | Standard input stream - by default 'connected' to the standard input device (i.e., keyboard). Instance of istream . |
cout | Standard output stream - by default 'connected' to the standard input device (i.e., console). Instance of ostream . |
cerr | Standard error stream - by default 'connected' to the standard error device (i.e., console). Instance of ostream (unbuffered) . |
clog | Standard error stream - by default 'connected' to the standard log device (i.e., console). Instance of ostream (unbuffered) . |
Streams have useful member functions to control formatting.
Can be used on input and output streams
The time of the effect on the stream varies
Can be used as member functions or as a manipulator
xxxxxxxxxx
21std::cout.width(10); // Member function
2std::cout << std::setw(10); // Manipulator
Here, we'll focus on 'manipulator' usage.
Common Stream Manipulators
Boolean
boolalpha
, noboolalpha
Integer
dec
, hex
, oct
, showbase
, noshowbase
, showpos
, noshowpos
, uppercase
, nouppercase
Floating point
fixed
, scientific
, setprecision
, showpoint
, noshowpoint
, showpos
, noshowpos
Field width, justification and fill
setw
, left
, right
, internal
, setfill
Others
endl
, flush
, skipws
, noskipws
, ws
Used to format boolean types
Default when displaying boolean values is 1 or 0
Sometimes the string true or false are more appropriate
Formatting boolean types
xxxxxxxxxx
21std::cout << (10 == 10) << std::endl; // 1
2std::cout << (10 == 20) << std::endl; // 0
xxxxxxxxxx
21std::cout << std::noboolalpha; // 1 or 0
2std::cout << std::boolalpha; // true or fase
All further boolean output will be affected.
Method version
xxxxxxxxxx
21std::cout.setf(std::ios::boolalpha);
2std::cout.setf(std::ios::noboolalpha);
Reset to default
xxxxxxxxxx
11std::cout << std::resetiosflags(std::ios::boolalpha);
Default when displaying integer value is:
dec
(base 10)
noshowbase
- prefix used to show hexadecimal or octal
nouppercase
- when displaying a prefix and hex values it will be lower case
noshowpos
- no +
is displayed for positive numbers
These manipulators affect all further output to the stream.
Setting base
xxxxxxxxxx
51int num{255};
2
3std::cout << std::dec << num << std::endl; // 255
4std::cout << std::hex << num << std::endl; // ff
5std::cout << std::oct << num << std::endl; // 377
Showing the base
xxxxxxxxxx
61int num{255};
2
3std::cout << std::showbase; // std::noshowbase
4std::cout << std::dec << num << std::endl; // 255
5std::cout << std::hex << num << std::endl; // 0xff ('0x' prefix for hexadecimal)
6std::cout << std::oct << num << std::endl; // 0377 ('0' prefix for octal)
Displaying hex in uppercase
xxxxxxxxxx
41int num{255};
2
3std::cout << std::showbase << std::uppercase; // std::nouppercase
4std::cout << std::hex << num << std::endl; // 0XFF (note capitalized 'XFF')
Displaying the positive sign
xxxxxxxxxx
101int num1{255};
2int num2{-255};
3
4std::cout << num1 << std::endl; // 255
5std::cout << num2 << std::endl; // -255
6
7std::cout << std::showpos; // std::noshowpos
8
9std::cout << num1 << std::endl; // +255
10std::cout << num2 << std::endl; // -255
Setting and resetting integer types
Set using setf
xxxxxxxxxx
31std::cout.setf(std::ios::showbase);
2std::cout.setf(std::ios::uppercase);
3std::cout.setf(std::ios::showpos);
Reset to defaults
xxxxxxxxxx
41std::cout << std::resetiosflags(std::ios::basefield);
2std::cout << std::resetiosflags(std::ios::showbase);
3std::cout << std::resetiosflags(std::ios::showpos);
4std::cout << std::resetiosflags(std::ios::uppercase);
Default when displaying floating point value is:
setprecision
- number of digits displayed (6)
fixed
- not fixed to a specific number of digits after the decimal point
noshowpoint
- trailing zeros that are not displayed
nouppercase
- when displaying in scientific notation
noshowpos
- no +
is displayed for positive numbers
These manipulators affect all further output to the stream.
Precision
xxxxxxxxxx
21double num{1234.5678};
2std::cout << num << std::endl; // 1234.57 (Notice precision is 6 and rounding)
xxxxxxxxxx
21double num{123456789.987654321};
2std::cout << num << std::endl; // 1.23457e+008 (Notice precision is 6)
xxxxxxxxxx
31double num{123456789.987654321};
2std::cout << std::setprecision(9);
3std::cout << num << std::endl; // 123456790 (Note that rounding occurs)
Fixed
xxxxxxxxxx
31double num{123456789.987654321};
2std::cout << std::fixed;
3std::cout << num << std::endl; // 123456789.987654 (Precision 6 from the decimal)
xxxxxxxxxx
31double num{123456789.987654321};
2std::cout << std::setprecision(3) << std::fixed;
3std::cout << num << std::endl; // 123456789.988 (Precision 3 from the decimal)
Note that rounding occurs.
Scientific
xxxxxxxxxx
31double num{123456789.987654321};
2std::cout << std::setprecision(3) << std::scientific;
3std::cout << num << std::endl; // 1.23e+008 (Precision 3)
Scientific uppercase
xxxxxxxxxx
31double num{123456789.987654321};
2std::cout << std::setprecision(3) << std::scientific << std::uppercase;
3std::cout << num << std::endl; // 1.23E+008 (Note the capital 'E')
Displaying the positive sign
xxxxxxxxxx
31double num{123456789.987654321};
2std::cout << std::setprecision(3) << std::fixed << std::showpos;
3std::cout << num << std::endl; // +123456789.988 (Note the leading '+')
Trailing zeros
xxxxxxxxxx
51double num{12.34};
2std::cout << num << std::endl; // 12.34 (Note no trailing zeros - default)
3std::cout << std::showpoint;
4std::cout << std::endl; // 12.3400 (Note trailing zeros up to precision)
5
Returning to general settings
unsetf
xxxxxxxxxx
11std::cout.unsetf(std::ios::scientific | std::ios::fixed);
or
xxxxxxxxxx
11std::cout << std::resetiosflags(std::ios::floatfield);
Refer to the docs for other set/reset flags!
Default when displaying floating point value is:
setw
- not set by default
left
- when no field width, right
- when using field width
setfill
- not set by default (blank space is used by default)
Some of these manipulators affect only the next data element put on the stream.
Defaults
xxxxxxxxxx
51double num{1234.5678};
2std::string hello{"Hello"};
3std::cout << num << hello << std::endl; // 1234.57Hello
4std::cout << num << std::endl; // 1234.57
5std::cout << hello << std::endl; // Hello
Field width (setw
)
xxxxxxxxxx
51double num{1234.5678};
2std::string hello{"Hello"};
3
4std::cout << std::setw(10) << num << hello << std::endl;
5// ---1234.57Hello ('-' represents space)
xxxxxxxxxx
71double num{1234.5678};
2std::string hello{"Hello"};
3
4std::cout << std::setw(10) << num
5 << std::setw(10) << hello
6 << std::setw(10) << hello << std::endl;
7// ---1234.57-----Hello-----Hello ('-' represents space)
xxxxxxxxxx
81double num{1234.5678};
2std::string hello{"Hello"};
3
4std::cout << std::setw(10)
5 << std::left
6 << num // Only affects num!
7 << hello << std::endl;
8// 1234.57---Hello ('-' represents space)
xxxxxxxxxx
81double num{1234.5678};
2std::string hello{"Hello"};
3
4std::cout << std::setw(10) << num
5 << std::setw(10) << std::right << hello
6 << std::setw(15) << std::right << hello
7 << std::endl;
8// ---1234.57-----Hello----------Hello ('-' represents space)
Filling fixed width (setfill
)
xxxxxxxxxx
81double num{1234.5678};
2std::string hello{"Hello"};
3
4std::cout << std::setfill('*');
5std::cout << std::setw(10)
6 << num
7 << hello << std::endl;
8// ***1234.57Hello
fstream
and ifstream
)fstream
and ifstream
are commonly used for input files
#include <fstream>
Declare an fstream
or ifstream
object
Connect it to a file on your file system (opens it for reading)
Read data from the file via the stream
Close the stream
Opening a file for reading with fstream
xxxxxxxxxx
11std::fstream in_file{"../myfile.txt", std::ios::in};
Opening for reading in binary mode
xxxxxxxxxx
11std::fstream in_file{"../myfile.txt", std::ios::in | std::ios::binary};
Opening a file for reading with ifstream
xxxxxxxxxx
21std::ifstream in_file{"../myfile.txt", std::ios::in};
2std::ifstream in_file{"../myfile.txt"};
Open for reading in binary mode
xxxxxxxxxx
11std::ifstream in_file{"../myfile.txt", std::ios::binary};
Opening a file for reading with open()
xxxxxxxxxx
71std::ifstream in_file;
2std::string filename;
3std::cin >> filename; // Get the file name
4
5in_file.open(filename);
6// Or
7in_file.open(filename, std::ios::binary);
Check if file opened successfully (is_open()
)
xxxxxxxxxx
101if (in_file.is_open()) // Or simply 'if (in_file)' to test the stream object
2{
3 // Read from it
4}
5else
6{
7 // File could not be opened
8 // Does it exist?
9 // Should the program terminate?
10}
Closing a file
Always close any open files to flush out any unwritten data!
xxxxxxxxxx
11in_file.close();
Reading from files using >>
We can use the extraction operator for formatted read the same way we used it with cin
.
xxxxxxxxxx
61int num{};
2double total{};
3std::string name{};
4
5in_file >> num; // num <- 100
6in_file >> total >> name; // total <- 176.64, name <- "Jack"
Where the contents of in_file
is
xxxxxxxxxx
31100
2176.64
3Jack
Reading from files using getline()
We can use getline()
to read the file one line at a time.
xxxxxxxxxx
21std::string line{};
2std::getline(in_file, line); // line <- "This is a line"
Where the contents of in_file
is
xxxxxxxxxx
11This is a line
Reading a text file one line at a time
xxxxxxxxxx
191// Open file
2std::ifstream in_file{"../myfile.txt"};
3std::string line{};
4
5// Check if the file is open
6if (!in_file)
7{
8 std::cerr << "File open error" << std::endl;
9 return 1; // Exit the program (main)
10}
11
12while (!in_file.eof()) // While not at the end
13{
14 std::getline(in_file, line); // Read a line
15 std::cout << line << std::endl; // Display the line
16}
17
18// Close the file
19in_file.close();
The while
loop in the example above can be re-written as
xxxxxxxxxx
21while (std::getline(int_file, line)) // While not at the end read a line
2 std::cout << line << std::endl;
Reading text file one character at a time (get()
)
xxxxxxxxxx
181// Open file
2std::ifstream in_file{"../myfile.txt"};
3char c;
4
5// Check if the file is open
6if (!in_file)
7{
8 std::cerr << "File open error" << std::endl;
9 return 1; // Exit the program (main)
10}
11
12while (!in_file.get(c)) // While not at the end read a character
13{
14 std::cout << c; // Display the character
15}
16
17// Close the file
18in_file.close();
fstream
and ofstream
)fstream
and ofstream
are commonly used for output files
#include <fstream>
Declare an fstream
or ofstream
object
Connect it to a file on your file system (opens it for writing)
Write data to the file via the stream
Close the stream
Note
Output files will be created if they don't exist.
Output files will be overwritten (truncated) by default.
Can be opened so that new writes append.
Can be open in text or binary modes.
Opening a file for writing with fstream
xxxxxxxxxx
11std::fstream out_file{"../myfile.txt", std::ios::out};
Opening for writing in binary mode
xxxxxxxxxx
11std::fstream out_file{"../myfile.txt", std::ios::out | std::ios::binary};
Opening a file for writing with ofstream
xxxxxxxxxx
21std::ofstream out_file{"../myfile.txt", std::ios::out};
2std::ofstream out_file{"../myfile.txt"};
Open for writing in binary mode
xxxxxxxxxx
11std::ofstream out_file{"../myfile.txt", std::ios::binary};
Different actions upon opening a file for writing
xxxxxxxxxx
61// Truncate (discard contents) when opening
2std::ofstream out_file{"../myfile.txt", std::ios::trunc};
3// Append on each write
4std::ofstream out_file{"../myfile.txt", std::ios::app};
5// Seek to end of stream when opening
6std::ofstream out_file{"../myfile.txt", std::ios::ate};
Opening a file for writing with open()
xxxxxxxxxx
71std::ofstream out_file;
2std::string filename;
3std::cin >> filename; // Get the file name
4
5out_file.open(filename);
6// Or
7out_file.open(filename, std::ios::binary);
Check if file opened successfully (is_open()
)
xxxxxxxxxx
101if (out_file.is_open()) // Or simply 'if (out_file)' to test the stream object
2{
3 // Write to it
4}
5else
6{
7 // File could not be opened or created
8 // Does it exist?
9 // Should the program terminate?
10}
Closing a file
Always close any open files to flush out any unwritten data!
xxxxxxxxxx
11out_file.close();
Writing to files using <<
We can use the insertion operator for formatted write the same way we used it with cout
.
xxxxxxxxxx
71int num{100};
2double total{176.64};
3std::string name{"Jack"};
4
5out_file << num << "\n"
6 << total << "\n"
7 << name << std::endl;
The contents of in_file
will be
xxxxxxxxxx
31100
2176.64
3Jack
Copying a text file one line at a time
xxxxxxxxxx
261// Open files
2std::ifstream in_file{"../myfile.txt"};
3std::ofstream out_file{"../copy.txt"};
4
5// Check if the input file is open
6if (!in_file)
7{
8 std::cerr << "File open error" << std::endl;
9 return 1; // Exit the program (main)
10}
11
12// Check if the output file is open
13if (!out_file)
14{
15 std::cerr << "File create error" << std::endl;
16 return 1; // Exit the program (main)
17}
18
19std::string line{};
20
21while (std::getline(int_file, line)) // While not at the end read a line
22 out_file << line << std::endl; // Write a line to the output file
23
24// Close the files
25in_file.close();
26out_file.close();
Copying a text file one character at a time (get()
/put()
)
xxxxxxxxxx
281// Open files
2std::ifstream in_file{"../myfile.txt"};
3std::ofstream out_file{"../copy.txt"};
4
5// Check if the input file is open
6if (!in_file)
7{
8 std::cerr << "File open error" << std::endl;
9 return 1; // Exit the program (main)
10}
11
12// Check if the output file is open
13if (!out_file)
14{
15 std::cerr << "File create error" << std::endl;
16 return 1; // Exit the program (main)
17}
18
19char c;
20
21while (!in_file.get(c)) // While not at the end read a character
22{
23 out_file.put(c); // Write the character to the file
24}
25
26// Close the files
27in_file.close();
28out_file.close();
Allow us to read or write from strings in memory much as we would read/write to files
Very powerful
Very useful for data validation
Using string streams
#include <sstream>
Declare an stringstream
, istringstream
, or ostringstream
object
Connect it to a std::string
Read/write data from/to the string stream using formatted I/O
Reading from a stringstream
xxxxxxxxxx
91
2
3int num{};
4double total{};
5std::string name{};
6std::string info{"Moe 100 1234.5"};
7
8std::istringstream iss{info};
9iss >> name >> num >> total;
Writing to a stringstream
xxxxxxxxxx
91
2
3int num{100};
4double total{1234.5};
5std::string name{"Moe"};
6
7std::ostringstream oss{};
8oss << name << " " << num << " " << total;
9std::cout << oss.str() << std::endl;
Validating input with stringstream
xxxxxxxxxx
111int value{};
2std::string input{};
3
4std::cout << "Enter an integer: ";
5std::cin >> input;
6
7std::stringstream ss{input};
8if (ss >> value)
9 std::cout << "An integer was entered";
10else
11 std::cout << "An integer was NOT entered";