The C language did not build the input/output facilities into the language. In other words, there is no keyword like read
or write
. Instead, it left the IO to the compiler as external library functions (such as printf
and scanf
in stdio
library). The ANSI C standard formalized these IO functions into Standard IO package (stdio.h
). C++ continues this approach and formalizes IO in libraries such as iostream
and fstream
.
Features
- C++ IO is type safe. IO operations are defined for each of the type. If IO operations are not defined for a particular type, compiler will generate an error.
- C++ IO operations are based on streams of bytes and are device independent. The same set of operations can be applied to different types of IO devices.
Stream IO
Streams
C/C++ IO are based on streams, which are sequence of bytes flowing in and out of the programs (just like water and oil flowing through a pipe). In input operations, data bytes flow from an input source (such as keyboard, file, network or another program) into the program. In output operations, data bytes flow from the program to an output sink (such as console, file, network or another program). Streams acts as an intermediaries between the programs and the actual IO devices, in such the way that frees the programmers from handling the actual devices, so as to archive device independent IO operations.
C++ provides both the formatted and unformatted IO functions. In formatted or high-level IO, bytes are grouped and converted to types such as int
, double
, string or user-defined types. In unformatted or low-level IO, bytes are treated as raw bytes and unconverted. Formatted IO operations are supported via overloading the stream insertion (<<
) and stream extraction (>>
) operators, which presents a consistent public IO interface.
To perform input and output, a C++ program:
- Construct a stream object.
- Connect (Associate) the stream object to an actual IO device (e.g., keyboard, console, file, network, another program).
- Perform input/output operations on the stream, via the functions defined in the stream's pubic interface in a device independent manner. Some functions convert the data between the external format and internal format (formatted IO); while other does not (unformatted or binary IO).
- Disconnect (Dissociate) the stream to the actual IO device (e.g., close the file).
- Free the stream object.
C++ IO Headers, Templates and Classes
Headers
C++ IO is provided in headers <iostream>
(which included <ios>
, <istream>
, <ostream>
and <streambuf>
), <fstream>
(for file IO), and <sstream>
(for string IO). Furthermore, the header <iomanip>
provided manipulators such as setw()
, setprecision()
setfill()
and setbase()
for formatting.
Template Classes
In order to support various character sets (char
and wchar_t
in C++98/03; and char16_t
, char32_t
introduced in C++11), the stream classes are written as template classes, which could be instantiated with an actual character type. Most of the template classes take two type parameters. For example,
template <class charT, class traits = char_traits<charT> > class basic_istream; template <class charT, class traits = char_traits<charT> > class basic_ostream;
where:
charT
is the character type, such aschar
orwchar_t
;traits
, of another template classchar_traits<charT>
, defined the properties of the character operations such as the collating sequence (sorting order) of character set.
Template Instantiations and typedef
As mention, the basic_xxx
template classes can be instantiated with a character type, such as char
and wchar_t
. C++ further provides typedef
statements to name these classes:
typedef basic_ios<char> ios; typedef basic_ios<wchar_t> wios; typedef basic_istream<char> istream; typedef basic_istream<wchar_t> wistream; typedef basic_ostream<char> ostream; typedef basic_ostream<wchar_t> wostream; typedef basic_iostream<char> iostream; typedef basic_iostream<wchar_t> wiostream; typedef basic_streambuf<char> streambuf; typedef basic_streambuf<wchar_t> wstreambuf;
Specialization Classes for char type
We shall focus on the specialization classes for char
type:
ios_base
andios
: superclasses to maintain common stream properties such as format flag, field width, precision and locale. The superclassios_base
(which is not a template class) maintains data that is independent of the template parameters; whereas the subclassios
(instantiation of templatebasic_ios<char>
) maintains data which is dependent of the template parameters.istream
(basic_istream<char>
),ostream
(basic_ostream<char>
): provide the input and output public interfaces.iostream
(basic_iostream<char>
): subclass of bothistream
andostream
, which supports bidirectional input and output operations. Take note thatistream
andostream
are unidirectional streams; whereasiostream
is bidirectional.basic_iostream
template andiostream
class is declared in the<istream>
header, not<iostream>
header.ifstream
,ofstream
andfstream
: for file input, output and bidirectional input/output.istringstream
,ostringstream
andstringstream
: forstring
buffer input, output and bidirectional input/output.streambuf
,filebuf
andstringbuf
: provide memory buffer for the stream, file-stream and string-stream, and the public interface for accessing and managing the buffer.
Buffered IO
[TODO]
The <iostream> Header and the Standard Stream Objects: cin, cout, cerr and clog
The <iostream>
header also included the these headers: <ios>
, <istream>
, <ostream>
and <streambuf>
. Hence, your program needs to include only the <iostream>
header for IO operations.
The <iostream>
header declares these standard stream objects:
cin
(ofistream
class,basic_istream<char>
specialization),wcin
(ofwistream
class,basic_istream<wchar_t>
specialization): corresponding to the standard input stream, defaulted to keyword.cout
(ofostream
class),wcout
(ofwostream
class): corresponding to the standard output stream, defaulted to the display console.cerr
(ofostream
class),wcerr
(ofwostream
class): corresponding to the standard error stream, defaulted to the display console.clog
(ofostream
class),wclog
(ofwostream
class): corresponding to the standard log stream, defaulted to the display console.
The Stream Insertion << and Stream Extraction >> Operators
Formatted output is carried out on streams via the stream insertion <<
and stream extraction >>
operators. For example,
cout << value; cin >> variable;
Take note that cin
/cout
shall be the left operand and the data flow in the direction of the arrows.
The <<
and >>
operators are overloaded to handle fundamental types (such as int
and double
), and classes (such as string
). You can also overload these operators for your own user-defined types.
The cin <<
and cout >>
return a reference to cin
and cout
, and thus, support cascading operations. For example,
cout << value1 << value2 << .... ; cin >> variable1 << variable2 << .... ;
The ostream Class
The ostream
class is a typedef
to basic_ostream<char>
. It contains two set of output functions: formatted output and unformatted output.
- The formatted output functions (via overloaded stream insertion operator
<<
) convert numeric values (such asint
,double
) from their internal representations (e.g., 16-/32-bitint
, 64-bitdouble
) to a stream of characters that representing the numeric values in text form. - The unformatted output functions (e.g.,
put()
,write()
) outputs the bytes as they are, without format conversion.
Formatting Output via the Overloaded Stream Insertion << Operator
The ostream
class overloads the stream insertion <<
operator for each of the C++ fundamental types (char
, unsigned char
, signed char
, short
, unsigned short
, int
, unsigned int
, long
, unsigned long
, long long
(C++11), unsigned long long
(C++11), float
, double
and long double
. It converts a numeric value from its internal representation to the text form.
ostream & operator<< (type) // type of int, double etc
The <<
operator returns a reference to the invoking ostream
object. Hence, you can concatenate <<
operations, e.g., cout << 123 << 1.13 << endl;
.
The <<
operator is also overloaded for the following pointer types:
const char *
,const signed char *
,const unsigned char *
: for outputting C-strings and literals. It uses the terminating null character to decide the end of thechar
array.void *
: can be used to print an address.
For example,
char str1[] = "apple"; const char * str2 = "orange"; cout << str1 << endl; // with char *, print C-string cout << str2 << endl; // with char *, print C-string cout << (void *) str1 << endl; // with void *, print address (regular cast) cout << static_cast<void *>(str2) << endl; // with void *, print address
Flushing the Output Buffer
You can flush the output buffer via:
flush
member function or manipulator:// Member function of ostream class - std::ostream::flush ostream & flush (); // Example cout << "hello"; cout.flush(); // Manipulator - std::flush ostream & flush (ostream & os); // Example cout << "hello" << flush;
endl
manipulator, which inserts a newline and flush the buffer. Outputting a newline character'\n'
may not flush the output buffer; butendl
does.// Manipulator - std::endl ostream & endl (ostream & os)
cin
: output buffer is flushed when input is pending, e.g.,cout << "Enter a number: "; int number; cin << number; // flush output buffer so as to show the prompting message
The istream class
Similar to the ostream
class, the istream
class is a typedef
to basic_istream<char>
. It also supports formatted input and unformatted input.
- In formatting input, via overloading the
>>
extraction operator, it converts the text form (a stream of character) into internal representation (such as 16-/32-bitint
, 64-bytedouble
). - In unformatting input, such as
get()
,getlin()
,read()
, it reads the characters as they are, without conversion.
Formatting Input via the Overloaded Stream Extraction >> Operator
The istream
class overloads the extraction >>
operator for each of the C++ fundamental types (char
, unsigned char
, signed char
, short
, unsigned short
, int
, unsigned int
, long
, unsigned long
, long long
(C++11), unsigned long long
(C++11), float
, double
and long double
. It performs formatting by converting the input texts into the internal representation of the respective types.
istream & operator<< (type &) // type of int, double etc.
The >>
operator returns a reference to the invoking istream
object. Hence, you can concatenate >>
operations, e.g., cin >> number1 << number2 <<...
.
The >>
operator is also overloaded for the following pointer types:
const char *
,const signed char *
,const unsigned char *
: for inputting C-strings. It uses whitespace as delimiter and adds a terminating null character to the C-string.
[TODO] Read "C-string input".
Flushing the Input Buffer - ignore()
You can use the ignore()
to discard characters in the input buffer:
istream & ignore (int n = 1, int delim = EOF); // Read and discard up to n characters or delim, whichever comes first // Examples cin.ignore(numeric_limits<streamsize>::max()); // Ignore to the end-of-file cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Ignore to the end-of-line
Unformatted Input/Output Functions
put(), get() and getline()
The ostream
's member function put()
can be used to put out a char
. put()
returns the invoking ostream
reference, and thus, can be cascaded. For example,
// ostream class ostream & put (char c); // put char c to ostream
// Examples
cout.put('A');
cout.put('A').put('p').put('p').put('\n');
cout.put(65);
// istream class // Single character input int get (); // Get a char and return as int. It returns EOF at end-of-file istream & get (char & c); // Get a char, store in c and return the invoking istream reference // C-string input istream & get (char * cstr, streamsize n, char delim = '\n'); // Get n-1 chars or until delimiter and store in C-string array cstr. // Append null char to terminate C-string // Keep the delim char in the input stream. istream & getline (char * cstr, streamsize n, char delim = '\n'); // Same as get(), but extract and discard delim char from the // input stream.
// Examples int inChar; while ((inChar = cin.get()) != EOF) { // Read till End-of-file cout.put(inchar); }
[TODO] Example
read(), write() and gcount()
// istream class istream & read (char * buf, streamsize n); // Read n characters from istream and keep in char array buf. // Unlike get()/getline(), it does not append null char at the end of input. // It is used for binary input, instead of C-string. streamsize gcount() const; // Return the number of character extracted by the last unformatted input operation // get(), getline(), ignore() or read(). // ostream class ostream & write (const char * buf, streamsize n) // Write n character from char array.
// Example
[TODO]
Other istream functions - peek() and putback()
char peek (); //returns the next character in the input buffer without extracting it. istream & putback (char c); // insert the character back to the input buffer.
States of stream
The steam superclass ios_base
maintains a data member to describe the states of the stream, which is a bitmask of the type iostate
. The flags are:
eofbit
: set when an input operation reaches end-of-file.failbit
: The last input operation failed to read the expected characters or output operation failed to write the expected characters, e.g.,getline()
reads n characters without reaching delimiter character.badbit
: serious error due to failure of an IO operation (e.g. file read/write error) or stream buffer.goodbit
: Absence of above error with value of 0.
These flags are defined as public static members in ios_base
. They can be accessed directly via ios_base::failbit
or via subclasses such as cin::failbit
, ios::failbit
. However, it is more convenience to use these public member functions of ios
class:
good()
: returnstrue
ifgoodbit
is set (i.e., no error).eof()
: returnstrue
ifeofbit
is set.fail()
: returnstrue
iffailbit
orbadbit
is set.bad()
: returnstrue
ifbadbit
is set.clear()
: cleareofbit
,failbit
andbadbit
.
Formatting Input/Output via Manipulators in <iomanip> and <iostream>
C++ provides a set of manipulators to perform input and output formatting:
<iomanip>
header:setw()
,setprecision()
,setbas()
,setfill()
.<iostream>
header:fixed|scientific
,left|right|internal
,boolalpha|noboolalpha
, etc.
Default Output Formatting
The ostream
's <<
stream insertion operator is overloaded to convert a numeric value from its internal representation (e.g., 16-/32-bit int
, 64-bit double
) to the text form.
- By default, the values are displayed with a field-width just enough to hold the text, without additional leading or trailing spaces. You need to provide spaces between the values, if desired.
- For integers, all digits will be displayed, by default. For example,
cout << "|" << 1 << "|" << endl; // |1| cout << "|" << -1 << "|" << endl; // |-1| cout << "|" << 123456789 << "|" << endl; // |123456789| cout << "|" << -123456789 << "|" << endl; // |-123456789|
- For floating-point numbers, the default precision is 6 digits, except that the trailing zeros will not be shown. This default precision (of 6 digits) include all digits before and after the decimal point, but exclude the leading zeros. Scientific notation (E-notation) will be used if the exponent is 6 or more or -5 or less. In scientific notation, the default precision is also 6 digits; the exponent is displayed in 3 digits with plus/minus sign (e.g., +006, -005). For example,
cout << "|" << 1.20000 << "|" << endl; // |1.2| (trailing zeros not displayed) cout << "|" << 1.23456 << "|" << endl; // |1.23456| (default precision is 6 digits) cout << "|" << -1.23456 << "|" << endl; // |-1.23456| cout << "|" << 1.234567 << "|" << endl; // |1.23457| cout << "|" << 123456.7 << "|" << endl; // |123457| cout << "|" << 1234567.89 << "|" << endl; // |1.23457e+006| (scientific-notation for e>=6) cout << "|" << 0.0001234567 << "|" << endl; // |0.000123457| (leading zeros not counted towards precision) cout << "|" << 0.00001234567 << "|" << endl; // |1.23457e-005| (scientific-notation for e<=-5)
bool
values are displayed as 0 or 1 by default, instead oftrue
orfalse
.
Field Width (setw), Fill Character (setfill) and Alignment (left|right|internal)
The ios_base
superclass (included in <iostream>
header) maintains data members for field-width (width
) and formatting flags (fmtflags
); and provides member functions (such as width()
, setf()
) for manipulating them.
However, it is more convenience to use the so-called IO manipulators, which returns a reference to the invoking stream object and thus can be concatenated in <<
operator (e.g., cout << setfill(':') << left << setw(5) <<...
). They are:
setw()
manipulator (in<iomanip>
header) to set the field width.setfill()
manipulator (in<iomanip>
header) to set the fill characterleft|right|internal
manipulator (in<iostream>
header) to set the text alignment.
The default field-width is 0, i.e., just enough space to display the value. C++ never truncates data, and will expand the field to display the entire value if the field-width is too small. The setw()
operation is non-sticky. That is, it is applicable only to the next IO operation, and reset back to 0 after the operation. The field-width property is applicable to both output and input operations.
Except setw()
, all the other IO manipulators are sticky, i.e., they take effect until a new value is set.
// Test setw() - need <iomanip> cout << "|" << setw(5) << 123 << "|" << 123 << endl; // | 123|123 // setw() is non-sticky. "|" and 123 displayed with default width cout << "|" << setw(5) << -123 << "|" << endl; // | -123|123 // minus sign is included in field width cout << "|" << setw(5) << 1234567 << "|" << endl; // |1234567| // no truncation of data // Test setfill() and alignment (left|right|internal) cout << setfill('_'); // Set the fill character (sticky) cout << setw(6) << 123 << setw(4) << 12 << endl; // ___123__12 cout << left; // left align (sticky) cout << setw(6) << 123 << setw(4) << 12 << endl; // 123___12__
Example: Alignment
cout << showpos; // show positive sign cout << '|' << setw(6) << 123 << '|' << endl; // | +123| (default alignment) cout << left << '|' << setw(6) << 123 << '|' << endl; // |+123 | cout << right << '|' << setw(6) << 123 << '|' << endl; // | +123| cout << internal << '|' << setw(6) << 123 << '|' << endl; // |+ 123|
The internal
alignment left-align the sign, but right-align the number, as illustrated.
[TODO] Example of field-width for input operations
You can also use ostream
's member function width()
(e.g. cout.width(n)
) to set the field width, but width()
cannot be used with cout <<
operator.
Floating-point Format (fixed|scientific) and Precision (setprecision)
The IO stream superclass ios_base
also maintains data member for the floating-point precision and display format; and provides member functions (such as precision()
) for manipulating them.
Again, it is more convenience to use IO manipulators, which can be concatenated in <<
. They are:
setprecision()
manipulator (in<iomanip>
header) to set the precision of floating-point number.fixed|scientific
manipulators (in<iostream>
header)to set the floating-point display format.
Floating point number can be display in 3 formatting modes: default
|fixed|scientific
. The precision is interpreted differently in default and non-default modes (due to legacy).
- In default mode (neither
fixed
norscientific
used), a floating-point number is displayed in fixed-point notation (e.g.,12.34
) for exponent in the range of[-4, 5]
; and scientific notation (e.g.,1.2e+006
) otherwise. The precision in default mode includes digits before and after the decimal point but exclude the leading zeros. Fewer digits might be shown as the trailing zeros are not displayed. The default precision is 6. See the earlier examples for default mode with default precision of 6.
As mentioned, the trailing zeros are not displayed in default mode, you can use manipulatorshowpoint|noshowpoint
to show or hide the trailing zeros. - In both
fixed
(e.g.,12.34
) andscientific
(e.g.,1.2e+006
), the precision sets the number of digits after decimal point. The default precision is also 6.
For examples,
// default floating-point format cout << "|" << 123.456789 << "|" << endl; // |123.457| (fixed-point format) // default precision is 6, i.e., 6 digits before and after the decimal point cout << "|" << 1234567.89 << "|" << endl; // |1.23457e+006| (scientific-notation for e>=6) // default precision is 6, i.e., 6 digits before and after the decimal point // showpoint - show trailing zeros in default mode cout << showpoint << 123. << "," << 123.4 << endl; // 123.000,123.400 cout << noshowpoint << 123. << endl; // 123 // fixed-point formatting cout << fixed; cout << "|" << 1234567.89 << "|" << endl; // |1234567.890000| // default precision is 6, i.e., 6 digits after the decimal point // scientific formatting cout << scientific; cout << "|" << 1234567.89 << "|" << endl; // |1.234568e+006| // default precision is 6, i.e., 6 digits after the decimal point // Test precision cout << fixed << setprecision(2); // sticky cout << "|" << 123.456789 << "|" << endl; // |123.46| cout << "|" << 123. << "|" << endl; // |123.00| cout << setprecision(0); cout << "|" << 123.456789 << "|" << endl; // |123|
You can also use ostream
's member function precision(n)
(e.g. cout.precision(n)
) to set the floating-point precision, but precision()
cannot be used with cout <<
operator.
Integral Number Base (dec|oct|hex, setbase)
C++ support number bases (radixes) of decimal, hexadecimal and octal. You can use the following manipulators (defined in ios_base
class, included in <iostream>
header) to manipulate the integral number base:
hex|dec|oct
: Set the integral number base. Negativehex
andoct
are displayed in 2's complement format. Alternatively, you can usesetbase(8|10|16)
(in header<iomanip>
).showbase|noshowbase
: writehex
values with0x
prefix; andoct
values with0
prefix.showpos|noshowpos
: write positivedec
value with + sign.uppercase|nouppercase
: write uppercase in certain insertion operations, e.g., hex digits. It does not convert characters or strings to uppercase!
These manipulators are sticky.
For examples,
cout << 1234 << endl; // 1234 (default is dec) cout << hex << 1234 << endl; // 4d2 cout << 1234 << "," << -1234 << endl; // 4d2,fffffb2e // (hex is sticky, negative number in 2's complement) cout << oct << 1234 << endl; // 2322 cout << 1234 << "," << -1234 << endl; // 2322,37777775456 cout << setbase(10) << 1234 << endl; // 1234 (setbase requires <iomanip> header) // showbase - show hex with 0x prefix; oct with 0 prefix cout << showbase << 123 << "," << hex << 123 << "," << oct << 123 << endl; // 123,0x7b,0173 cout << noshowbase << dec; // showpos - show dec's plus (+) sign cout << showpos << 123 << endl; // +123 // uppercase - display in uppercase (e.g., hex digits) cout << uppercase << hex << 123 << endl; // 7B
bool values (boolalpha|noboolalpha)
boolalpha|noboolalpha
: read/write bool value as alphabetic stringtrue
orfalse
.// boolalpha - display bool as true/false cout << boolalpha << false << "," << true << endl; // false,true cout << noboolalpha << false << "," << true << endl; // 0,1
Other manipulators
skipws|noskipws
: skip leading white spaces for certain input operations.unitbuf|nounibuf
: flush output after each insertion operation.
Notes
- You need to include the
<iomanip>
header forsetw()
,setprecision()
,setfill()
, andsetbase()
. - You can use
ios_base
's (in<iostream>
header) member functionssetf()
andunsetf()
to set the individual formatting flags. However, they are not as user-friendly as using manipulators as discussed above. Furthermore, they cannot be used withcout <<
operator.
The C++ string class Input/Output
[TODO]
File Input/Output (Header <fstream>)
C++ handles file IO similar to standard IO. In header <fstream>
, the class ofstream
is a subclass of ostream
; ifstream
is a subclass of istream
; and fstream
is a subclass of iostream
for bi-directional IO. You need to include both <iostream>
and <fstream>
headers in your program for file IO.
To write to a file, you construct a ofsteam
object connecting to the output file, and use the ostream
functions such as stream insertion <<
, put()
and write()
. Similarly, to read from an input file, construct an ifstream
object connecting to the input file, and use the istream
functions such as stream extraction >>
, get()
, getline()
and read()
.
File IO requires an additional step to connect the file to the stream (i.e., file open) and disconnect from the stream (i.e., file close).
File Output
The steps are:
- Construct an
ostream
object. - Connect it to a file (i.e., file open) and set the mode of file operation (e.g, truncate, append).
- Perform output operation via insertion
>>
operator orwrite()
,put()
functions. - Disconnect (close the file which flushes the output buffer) and free the
ostream
object.
#include <fstream>
.......
ofstream fout;
fout.open(filename, mode);
......
fout.close();
// OR combine declaration and open()
ofstream fout(filename, mode);
By default, opening an output file creates a new file if the filename does not exist; or truncates it (clear its content) and starts writing as an empty file.
open(), close() and is_open()
void open (const char* filename, ios::openmode mode = ios::in | ios::out); // open() accepts only C-string. For string object, need to use c_str() to get the C-string void close (); // Closes the file, flush the buffer and disconnect from stream object bool is_open (); // Returns true if the file is successfully opened
File Modes
File modes are defined as static public member in ios_base
superclass. They can be referenced from ios_base
or its subclasses - we typically use subclass ios
. The available file mode flags are:
ios::in
- open file for input operationios::out
- open file for output operationios::app
- output appends at the end of the file.ios::trunc
- truncate the file and discard old contents.ios::binary
- for binary (raw byte) IO operation, instead of character-based.ios::ate
- position the file pointer "at the end" for input/output.
You can set multiple flags via bit-or (|
) operator, e.g., ios::out | ios::app
to append output at the end of the file.
For output, the default is ios::out | ios::trunc
. For input, the default is ios::in
.
File Input
The steps are:
- Construct an
istream
object. - Connect it to a file (i.e., file open) and set the mode of file operation.
- Perform output operation via extraction
<<
operator orread()
,get()
,getline()
functions. - Disconnect (close the file) and free the
istream
object.
#include <fstream>
.......
ifstream fin;
fin.open(filename, mode);
......
fin.close();
// OR combine declaration and open()
ifstream fin(filename, mode);
By default, opening an input file ....
Example on Simple File IO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* Testing Simple File IO (TestSimpleFileIO.cpp) */ #include <iostream> #include <fstream> #include <cstdlib> #include <string> using namespace std; int main() { string filename = "test.txt"; // Write to File ofstream fout(filename.c_str()); // default mode is ios::out | ios::trunc if (!fout) { cerr << "error: open file for output failed!" << endl; abort(); // in <cstdlib> header } fout << "apple" << endl; fout << "orange" << endl; fout << "banana" << endl; fout.close(); // Read from file ifstream fin(filename.c_str()); // default mode ios::in if (!fin) { cerr << "error: open file for input failed!" << endl; abort(); } char ch; while (fin.get(ch)) { // till end-of-file cout << ch; } fin.close(); return 0; } |
Program Notes:
- Most of the
<fstream>
functions (such as constructors,open()
) supports filename in C-string only. You may need to extract the C-string fromstring
object via thec_str()
member function. - You could use
is_open()
to check if the file is opened successfully. - The
get(char &)
function returns a null pointer (converted tofalse
) when it reaches end-of-file.
Binary file, read() and write()
We need to use read()
and write()
member functions for binary file (file mode of ios::binary
), which read/write raw bytes without interpreting the bytes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* Testing Binary File IO (TestBinaryFileIO.cpp) */ #include <iostream> #include <fstream> #include <cstdlib> #include <string> using namespace std; int main() { string filename = "test.bin"; // Write to File ofstream fout(filename.c_str(), ios::out | ios::binary); if (!fout.is_open()) { cerr << "error: open file for output failed!" << endl; abort(); } int i = 1234; double d = 12.34; fout.write((char *)&i, sizeof(int)); fout.write((char *)&d, sizeof(double)); fout.close(); // Read from file ifstream fin(filename.c_str(), ios::in | ios::binary); if (!fin.is_open()) { cerr << "error: open file for input failed!" << endl; abort(); } int i_in; double d_in; fin.read((char *)&i_in, sizeof(int)); cout << i_in << endl; fin.read((char *)&d_in, sizeof(double)); cout << d_in << endl; fin.close(); return 0; } |
Random Access File
Random access file is associated with a file pointer, which can be moved directly to any location in the file. Random access is crucial in certain applications such as databases and indexes.
You can position the input pointer via seekg()
and output pointer via seekp()
. Each of them has two versions: absolute and relative positioning.
// Input file pointer (g for get) istream & seekg (streampos pos); // absolute position relative to beginning istream & seekg (streamoff offset, ios::seekdir way); // with offset (positive or negative) relative to seekdir: // ios::beg (beginning), ios::cur (current), ios::end (end) streampos tellg (); // Returns the position of input pointer // Output file pointer (p for put) ostream & seekp (streampos pos); // absolute ostream & seekp (streamoff offset, ios::seekdir way); // relative streampos tellp (); // Returns the position of output pointer
Random access file is typically process as binary file, in both input and output modes.
[TODO] Example
String Streams
C++ provides a <sstream>
header, which uses the same public interface to support IO between a program and string
object (buffer).
The string streams is based on ostringstream
(subclass of ostream
), istringstream
(subclass of istream
) and bi-directional stringstream
(subclass of iostream
).
typedef basic_istringstream<char> istringstream; typedef basic_ostringstream<char> ostringstream;
Stream input can be used to validate input data; stream output can be used to format the output.
ostringstream
explicit ostringstream (ios::openmode mode = ios::out); // default with empty string explicit ostringstream (const string & buf, ios::openmode mode = ios::out); // with initial str string str () const; // Get contents void str (const string & str); // Set contents
For example,
// construct output string stream (buffer) - need <sstream> header ostringstream sout; // Write into string buffer sout << "apple" << endl; sout << "orange" << endl; sout << "banana" << endl; // Get contents cout << sout.str() << endl;
The ostringstream
is responsible for dynamic memory allocation and management.
istringstream
explicit istringstream (ios::openmode mode = ios::in); // default with empty string explicit istringstream (const string & buf, ios::openmode mode = ios::in); // with initial string
For example,
// construct input string stream (buffer) - need <sstream> header istringstream sin("123 12.34 hello"); // Read from buffer int i; double d; string s; sin >> i >> d >> s; cout << i << "," << d << "," << s << endl;Link to "C++ Language References & Resources"