320 likes | 498 Views
Binary Files. Text Files vs. Binary Files. Text files: A way to store data in a secondary storage device using Text representation (e.g., ASCII characters) Binary files: A way to store data in a secondary storage device using the same binary representation as main memory. Binary vs. Text.
E N D
Text Files vs. Binary Files • Text files: • A way to store data in a secondary storage device using Text representation (e.g., ASCII characters) • Binary files: • A way to store data in a secondary storage device using the same binary representation as main memory.
Binary vs. Text ASCII Table
Data Records • Generally, when reading binary files, we read (or write) records. • A filepointer is used to track the current position in the file. • The current position is measured as a byte offset from the beginning of the file.
Random Access • Random access files allow the manipulation of the file pointer to read & write data from different locations within the file. • The next read or write will take place starting at the current location of the file pointer (fp) fp
Random Access • Text files only allow sequential access • Data must be read in the order it is stored, starting at the beginning of the file. • Binary files allow sequential & random access.
Sequential Access • When the current position of a binary file pointer is the beginning of a file, a read (or write) will advance the file pointer to the next record. 0 1 2 3 fp 0 1 2 3 fp
Random Access • However, the file pointer can also be placed randomly within the file, allowing access to specific records at any place in the file (similar to using arrays). 0 1 2 3 fp 0 1 2 3 fp
fstream • With text files, we have declared streams as an ifstream or ofstream. • With binary files is possible to declare simply an fstream and then open files for input, output, or both… fstream instr, outstr, inoutstr; instr.open(“infile.txt”, ios::in); outstr.open(“outfile.txt”, ios::out); inoutstr.open(“file.txt”, ios::in | ios::out); Bitwise OR
The Mode Parameter • ios::in • This indicates that the stream will be used for input. • ios::out • This indicates that the stream will be used for output. • ios::binary • This causes the file to be accessed as a binary file. If you need to specify more than one of them simply place a vertical bar between them.
file.clear() • It is possible to read a file over and over (you will do this in program 5). • You should be aware that there is a problem if during any read, you reach the end-of-file marker. This sets a flag that remains set the next time you try to read the file again. • To clear the eof flag, we use if(file.eof( )) file.clear( );
FYI • This is how you can reuse (i/o)fstreams… ifstream fin; fin.open("first.txt"); ... fin.close(); fin.clear(); fin.open("second.txt"); ...
Placing the file pointer • The file pointer moves throughout the file in offsets (the size of a single record). • Various arguments and fstream functions are associated with the file pointer: • ios::beg • ios::end • ios::cur • sizeof() • fstr.seekg() • fstr.tellg()
. seekg() • Moves the file pointer to another location within the file. • ios::beg • location (in bytes) from the beginning of the file. • ios::cur • location (in bytes) from the current file pointer position. • ios::end • location (in bytes) from the end of the file.
sizeof( ); • When moving through binary files, you must move in record size leaps. • sizeof( ) is a function to return the size of an argument (parameter). • sizeof(int) • will return the number of bytes necessary to store an integer (4 on our compiler). • sizeof(myObject) • will return the byte size of the declared object.
.seekg( ) – .seekp( ) • .seekp( ) can only be used with single directional streams. • Use .seekg( ) for files opened for both input and output. • These functions are used to move the file pointer within the file. • Two parameters are required • the number of bytes to move • the position to start measuring from
fstream fstr; fstr.seekg(); • To place the file pointer at the beginning of the file we could use: fstr.seekg(0, ios::beg); • To move the file pointer to the end of the file use: fstr.seekg(0, ios::end);
int main() { int x; fstream infile; infile.open("file.dat", ios::bin | ios::in); infile.seekg(9, ios::beg); // move 9 bytes from the beginning of the file … infile.seekg(-10, ios::cur); //back up 10 bytes from current position … infile.seekg(0,ios::end); // move to the end of the file infile.close(); }
To advance the pointer nrecords from the beginning of the file use: fstr.seekg(n * sizeof(record), ios::beg); 30 bytes 30 bytes 30 bytes 30 bytes 0 1 2 3 0 29|30 59|60 89|90 fp fstr.seekg(3 * sizeof(record), ios::beg); fstr.seekg(3 * 30, ios::beg); fstr.seekg(90, ios::beg);
To move back one record from the current location use: fstr.seekg(-sizeof(record), ios::cur); 30 bytes 30 bytes 30 bytes 30 bytes 0 1 2 3 0 29|30 59|60 89|90 fp fp
Practice • How would you place the pointer… n records from the end of a file fstr.seekg(-n * sizeof(record), ios::end); n records past the current position fstr.seekg(n * sizeof(record), ios::cur); pointing to the last record in a file fstr.seekg(-sizeof(record), ios::end);
.tellg( ); • This function will return the current byte location of the pointer. • The number of bytesfrom the beginning of the file. • You can use this to find the number of records in a file using: fstr.seekg(0, ios::end); numRec = fstr.tellg()/sizeof(record);
I/O with Binary Files • First you must open an fstream • It must be opened for both input and output ANDbinary mode fstream inOut; inOut.open("myFile.bin", ios::binary | ios::in | ios::out); if(!inOut.is_open( ))// same as inOut.fail( ) { cout << "error opening myFile.bin" << endl; exit(1); }
read( ) – write ( ) • read( ) and write( ) are fstream functions that perform I/O with a byte stream. • Each takes the address of a buffer and the number of bytes to transfer (count).
I/O Buffers • The buffer is an array of characters that stores the data as it is sent or received from a device. • Non-character data types require a type conversion, using the (char*) type cast. • This tells the compiler to consider the buffer as an array of characters (regardless of its contents).
Example fstream fstr; int intData; int arr[20]; // array of 20 integers fstr.read((char*) &intData, sizeof(int)); fstr.write((char*) arr, sizeof(arr));
program 5 • In program 5 you will not be reading the entire file into your program. • You will read a single record at a time, use it, update it, or delete it. • You will use the index.txt file to determine where records are in the binary file. • The Index class will help you do this
Update a Player • Find the player’s name in the index file and thus the location index associated with that player. • Use the index to move the file pointer to the desired record. • Read the Player record and update the data. • Move back one record in the file.(Why?) • Write the updated record to the file.
c:\>a.out PlayerRecord.binindex.txt int main(int argc, char *argv[]) • argc = 3 • argv[0] = a.out • argv[1] = PlayerRecord.bin • argv[2] = index.txt
Opening Files • to open the first file for input and the second file for output we could use ifstream first; inInv.open(argv[i]); ofstream second; outInv.open(argv[2]); • or fstream first, second; first.open(argv[1], ios::in); second.open(argv[2], ios::out);