Files and Streams
Imran Siddiqi
Dept. of CS
Bahria University, Islamabad
[email protected]
Recordings:
https://web.microsoftstream.com/video/59784c21-546e-4c2b-aab5-3225b03eacbb
https://web.microsoftstream.com/video/0f0954cb-51db-4c3e-9a29-409e3205c934
https://web.microsoftstream.com/video/64fbc063-01bd-41af-870b-40fea196fe68
C++ Stream Input/output
• C++ standard libraries provide an extensive set
of input/output capabilities.
• Streams of bytes, a sequence of bytes
– Bytes flows from devices to memory in input
stream; from memory to devices in output stream
– I/O operations are very important procedure in
computing
C++ Stream Input/output
C++ Stream Input/output
C++ Stream Input/output
C++ Stream Input/output
• operator overloading is applied to all of the
iostream classes
• cin is an instance of istream class
– cin>>grade;
• cout is an instance of ostream class
– cout<<grade;
Reading Data from/Writing Data to Files
Introduction
• Storage of data
– Arrays, variables are temporary
– Files are permanent
• Disk
The Data Hierarchy
• From smallest to largest
– Bit (binary digit)
• 1 or 0
• Everything in computer ultimately represented as bits
• Cumbersome for humans to use
• Character set
– Digits, letters, symbols used to represent data
– Every character represented by 1's and 0's
– Byte: 8 bits
• Can store a character (char)
The Data Hierarchy
• From smallest to largest (continued)
– Field: group of characters with some meaning
• Your name
– Record: group of related fields
• struct or class in C++
• In payroll system, could be name, SS#, address, wage
• Each field associated with same employee
• Record key: field used to uniquely identify record
– File: group of related records
• Payroll for entire company
• Sequential file: records stored by key
– Database: group of related files
• Payroll, accounts-receivable, inventory…
The Data Hierarchy
Sally Black
Tom Blue
Judy Green File
Iris Orange
Randy Red
Judy Green Record
Judy Field
01001010 Byte (ASCII character J)
1 Bit
Files and Streams
• C++ views file as sequence of bytes
– Ends with end-of-file marker
0 1 2 3 4 5 6 7 8 9 ... n-1
... end-of-file marker
Files and Streams
To open file, create objects
– Creates "line of communication" from object to file
– Classes
• ifstream (input only)
• ofstream (output only)
• fstream (I/O)
– Constructors take file name and file-open mode
ofstream fout( "filename", fileOpenMode );
– To attach a file later
ofstream fout;
fout.open( "filename", fileOpenMode);
Files & Streams
Files and Streams
example.txt
ofstream f(“example.txt”);
Opening a File
• The first operation generally performed on an object of one of
these classes is to associate it to a real file. This procedure is
known as to open a file.
• In order to open a file with a stream object we use its member
function open():
open (filename, mode);
Where filename represents the name of the file to be opened,
and mode is an optional parameter.
Opening a File
• File-open modes
Mode Description
ios::app Write all output to the end of the file.
ios::in Open a file for input.
ios::out Open a file for output.
ios::binary Open a file for binary (i.e., non-text) input or
output.
– ofstream opened for output by default
• ofstream fout ( "clients.dat", ios::out );
• ofstream fout ( "clients.dat");
Files & Streams
• Operations
– operator!
• if(!fout)
– Opened non-existent file for reading, wrong permissions
Files & Streams
• Operations
– Writing to file (just like cout)
• fout<< myVariable
– Closing file
• fout.close()
Example: Writing an integer to a file
abc.txt
2
Example: Reading an integer from file
abc.txt
2
Writing multiple variables to a file
abc.txt
2
3
4
Reading Data from File
abc.txt
2
3
4
Reading Data from File
• Reading files
– ifstream fin( "filename", ios::in );
– Operator !
• !fin tests if file was opened properly
– while (fin>> myVariable)
• Stops when EOF found (gets value 0)
Reading Data from File
abc.txt
2
3
4
Will read all data from the file until EOF is reached
Example: Writing Accounts Data to File
void write(){
ofstream fout("Accounts.txt",ios::out);
string name, ID;
int bal;
char type;
char choice;
do{
cout << "Enter accont ID:"; cin >> ID;
cout << "Enter customer name:"; cin >> name;
cout << "Enter account balance:"; cin >> bal;
cout << "Enter account type:"; cin >> type;
fout << ID << " " << name << " " << bal << " "<<type<<endl;
cout << "Another:";
cin >> choice;
} while (choice == 'y');
fout.close();
}
Example: Writing Accounts Data to File
void main(){
write();
}
Example: Reading Data from file and
showing to user
void read(){
ifstream fin("Accounts.txt");
string name, ID;
int bal;
char type;
while (fin >> ID >> name >> bal >> type){
cout << ID << "\t" << name << "\t" << bal <<"\t"<<type<< endl;
}
fin.close();
}
void main(){
read();
}
Example: Reading & Writing Data
Read account details from the file “Accounts.txt”.
For all savings account calculate the profit of 10%.
There is no profit in case of checking account.
Create a new file “Profit.txt” and write the total
profit amount against each account number
void readAndWrite(){
ifstream fin("Accounts.txt");
ofstream fout("Profit.txt");
string name, ID; int bal; char type;
int profit;
while (fin >> ID >> name >> bal >> type){
cout << ID << "\t" << name << "\t" << bal << "\t" << type <<
endl;
if (type == 'S’)
profit = bal * 0.1;
else
profit = 0;
fout << ID << " " << profit << endl;
}
fin.close();
fout.close();
}
Problem with << and >>
abc.txt
234
• No white space or new line character is written after each integer
• When reading data, program will not know it is one integer (234),
two integers (2,34,23,4) or three integers (2,3,4).
Problem with << and >>
• When using << and >> operators for reading
and writing – Always put a space or new line
character between multiple values.
File Position Pointers
• tellp() – for ofstream class
• tellg() – for ifstream class
• seekp()– for ofstream class
• seekg() – for ifstream class
• tell functions give current location of file pointer
• seek functions move file pointer
• g: get (input)
• p:put (output)
Reading Data from File
• File position pointers
– Number of next byte to read/write
– Functions to reposition pointer
• seekg (seek get for istream class)
• seekp (seek put for ostream class)
– seekg and seekp take offset and direction
• Offset: number of bytes relative to direction
• Direction (ios::beg default)
– ios::beg - relative to beginning of stream
– ios::cur - relative to current position
– ios::end - relative to end
Reading Data from File
• Examples
– fileObject.seekg(0)
• Goes to front of file (location 0) because ios::beg is
default
– fileObject.seekg(n)
• Goes to nth byte from beginning
– fileObject.seekg(n, ios::cur)
• Goes n bytes forward
– fileObject.seekg(y, ios::end)
• Goes y bytes from end
– seekp similar
Examples
Reading Data from File
• To find pointer location
– tellg and tellp
– location = fileObject.tellg()
Output:
Data:Sequence of characters
• ofstream and ifstream objects to write and read
data – “<<“ and “>>” operators
• Everything is written as sequence of characters
– ‘1’ vs ’10’ vs ‘100’ : In Memory all take 4 bytes, in file
it depends on number of digits in the integer
• Seek functions – Move file pointer
• Tell functions – Get location of file pointer
Updating Sequential-Access Files
• Updating sequential files
– Risk overwriting other data
– Example: change name "White" to "Worthington"
• Old data
300 White 0.00 400 Jones 32.87
• Insert new data
300 Worthington 0.00
300 White 0.00 400 Jones 32.87
Data gets overwritten
300 Worthington 0.00ones 32.87
– Formatted text different from internal representation
– Problem can be avoided, but awkward
Random-Access Files
• Instant access
– Want to locate record quickly
• Airline reservations, ATMs
– Sequential files must search through each one
• Random-access files are solution
– Instant access
– Insert record without destroying other data
– Update/delete items without changing other data
Random-Access Files
• C++ imposes no structure on files
– Programmer must create random-access files
– Simplest way: fixed-length records
• Calculate position in file from record size and key
0 100 200 300 400 500
} byte offsets
}
}
}
}
}
}
100 100 100 100 100 100
bytes bytes bytes bytes bytes bytes
Creating a Random-Access File
• "1234567" (char *) vs 1234567 (int)
– char * takes 8 bytes (1 for each character + null)
– int takes fixed number of bytes
– 123 same size in bytes as 1234567
• << operator and write()
– outFile << number
• Outputs number (int) as a char *
• Variable number of bytes
– outFile.write( const char *, size );
• Outputs raw bytes
• Takes pointer to memory location, number of bytes to write
– Copies data directly from memory into file
Creating a Random-Access File
• Example
outFile.write( reinterpret_cast<const char *>(&number),
sizeof( number ) );
– &number is an int *
• Convert to const char * with
reinterpret_cast
– sizeof(number)
• Size of number (an int) in bytes
Creating a Random-Access File
ofstream f("record.dat", ios::binary);
int x = 10;
int a = 5;
f.write(reinterpret_cast<char *>(&x), sizeof(x));
cout << "File Pointer:" << f.tellp() << endl;
f.write(reinterpret_cast<char *>(&a), sizeof(a));
cout << "File Pointer:" << f.tellp() << endl;
f.close();
\\Each integer is written to file in 4 bytes of memory
Creating a Random-Access File
ifstream f("record.dat", ios::binary);
int data;
f.read(reinterpret_cast<char *>(&data), sizeof(data));
cout << "Data Read:" << data << endl;
f.read(reinterpret_cast<char *>(&data), sizeof(data));
cout << "Data Read:" << data << endl;
f.close();
Writing Objects to File
class Point {
private:
int x;
int y;
public:
Point(int a = 0, int b = 0) {
x = a;
y = b;
}
void print() {
cout << "X:" << x << " Y:" << y << endl;
}
};
Writing Objects to File
void main(){
ofstream f("Points.dat", ios::binary);
Point p1(1, 2);
f.write(reinterpret_cast<char *>(&p1), sizeof(p1));
Point p2(3, 4);
f.write(reinterpret_cast<char *>(&p2), sizeof(p2));
f.close();
}
Directly Accessing a Record
• First Record: Byte 0 Byte 0
• Second Record: Byte 100 --------------Record 1-------------
• Third Record: Byte 200
• Fourth Record: Byte 300 Byte 100
--------------Record 2-------------
• Record 4:
– (4-1) x 100 = 300 Byte 200 --------------Record 3-------------
– (4-1) x size of one object
--------------Record 4-------------
Byte 300
• Record n:
– (n-1) x sizeof(object)
--------------Record 5-------------
Byte 400
Byte 499
Directly Accessing a Record
• Suppose 5 Point objects are written to a file
• Directly read record 5 Byte 0
• Location of record 5: P1 (1,1)
– (5-1) * sizeof(Point) Byte 8
P2 (2,2)
– 4 x 8 = 32
Byte 16
P3 (3,3)
• Use seek to move file
Byte 24
pointer P4 (4,4)
• Read Data
Byte 32
P5 (5,5)
Writing Data Randomly to a Random-
Access File
• Use seekp to write to exact location in file
– Where does the first record begin?
• Byte 0
– The second record?
• Byte 0 + sizeof(object)
– Any record?
• (Recordnum - 1) * sizeof(object)
void main() {
ofstream f("Points.dat", ios::binary);
int count;
cout << "How many records:";
cin >> count;
for (int i = 0; i < count; i++) {
Point p;
int x, y;
cout << "Enter x and y coordinates:" << endl;
cout << "X:";
cin >> x;
cout << "Y:";
cin >> y;
p.set(x, y);
f.write(reinterpret_cast<char *>(&p), sizeof(p));
}
f.close();
}
void main() {
ifstream f("Points.dat", ios::binary);
cout <<"Enter record number to read:";
int n;
cin >> n;
int fp = (n - 1) * sizeof(Point);
cout << "Record is at byte:" << fp << endl;
f.seekg(fp);
Point p;
f.read((char *)(&p), sizeof(p));
p.print();
f.close();
}