1. Trang chủ
  2. » Công Nghệ Thông Tin

A Complete Guide to Programming in C++ part 67 pptx

10 269 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 225,04 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

If you need access to specific infor-mation in such a file, you have to walk through the file from top to tail, and new records are always appended at the end of the file.. 䊐 Open Modes

Trang 1

䊐 Random File Access

So far we have only looked at sequential file access If you need access to specific infor-mation in such a file, you have to walk through the file from top to tail, and new records are always appended at the end of the file

Random file access gives you the option of reading and writing information directly at a

pre-defined position To be able to do this, you need to change the current file position explicitly, that is, you need to point the get/putpointer to the next byte to be manipu-lated After pointing the pointer, you can revert to using the read and write operations that you are already familiar with

䊐 Open Modes

One prerequisite of random file access is that the position of the records in the file can be precisely identified This implies opening the file in binary mode to avoid having to transfer additional escape characters to the file

ios::app | ios::binary;

fstream fstr("account.fle", mode);

This statement opens the file "Account.fle"in binary mode for reading and append-ing at end-of-file The file will be created if it did not previously exist Random read access

to the file is possible, but for write operations new records will be appended at the end of the file

To enable random read and write access to a file, the file can be opened as follows:

ios::binary;

fstream fstr("account.fle", mode);

However, this technique can only be used for existing files If the file does not exist, you can use the ios::truncflag to create it

The section “File State” discusses your error handling options if a file, such as

"account.fle"cannot be found

Trang 2

640 C H A P T E R 2 9 M O R E A B O U T F I L E S

Access point Positioning flag File

Beginning of the file ios::beg

Current position ios::cur

POSITIONING FOR RANDOM ACCESS

The three access points in a file

Trang 3

䊐 Discovering and Changing the Current Position

The file stream classes comprise methods to discover and change the current position in

a file The tellp()andtellg()methods return the current position of the putor

getpointers as a longvalue

This statement queries the current position of the read pointer in the myfile stream The current position is always returned as a byte offset relative to the beginning of the file

The current file position can be modified using the seekp()orseekg()method The position is stated as a byte offset, relative to either the beginning or end of the file,

or relative to the current position in the file

䊐 Positioning Flags

Threeios::seekdirtype positioning flags are defined in the iosclass for this pur-pose; these are ios::beg,ios::cur, and ios::end

Imagine you want to write the object accto the file "account.fle"at offset pos You can use the following statements to do so:

Example: ofstream fstr("account.fle", ios::out |

ios::binary);

fstr.seekp(pos, ios::begin);

acc.write( fstr );

This calls the write()method in the Accountclass, which allows an object to write its own data members to a file (see Chapter 18)

If you do not specify a positioning flag, the position will be assumed to be relative to the beginning of the file The statement used to position the write pointer in the last example can therefore be formulated as follows:

The byte offset can also be negative for calls to the methods seekp()andseekg() However, you cannot position the read/write pointer before the beginning of the file

In contrast, it is possible to place the pointer at a position after the end of the file and then perform a write operation, which will create a gap with unknown content in the file This only makes sense if all the empty slots in the file are of an equal length, as they can be overwritten later This option is often used when programming hash tables

Trang 4

642 C H A P T E R 2 9 M O R E A B O U T F I L E S

// index.h: Defines the class IndexEntry //

-#ifndef _INDEX_H

#define _INDEX_H

#include <fstream>

#include <iostream>

using namespace std;

class IndexEntry

{

private:

long key; // Key long recNr; // Offset

public:

IndexEntry(long k=0L, long n=0L) { key=k; recNr=n;} // Access methods and:

int recordSize() const { return sizeof(key) + sizeof(recNr); } fstream& write( fstream& ind) const;

fstream& read( fstream& ind);

fstream& write_at(fstream& ind, long pos) const; fstream& read_at( fstream& ind, long pos);

};

#endif

// index.cpp: Implements the methods //

-#include "index.h"

//

fstream& IndexEntry::write_at( fstream& ind, long pos) const

{ ind.seekp(pos);

ind.write((char*)&key, sizeof(key) );

ind.write((char*)&recNr, sizeof(recNr) );

return ind;

}

fstream& IndexEntry::read_at(fstream& ind, long pos)

{ ind.seekg(pos);

ind.read((char*)&key, sizeof(key) );

ind.read((char*)&recNr, sizeof(recNr));

return ind;

}

POSITIONING FOR RANDOM ACCESS (CONTINUED)

Representing an index entry

Trang 5

䊐 Using Positioning Methods

The following statements are commonly used for random positioning

seekg( 0L); and seekp( 0L, ios::end );

They set the current position to the beginning or end of a file You should be aware that the first argument is 0Lto indicate that longtype is required

If you need to determine the length of a file, you can point the getpointer to the end

of the file and then query the position of the pointer:

unsigned long count = fstr.tellg();

Thecountvariable will then contain the number of bytes occupied by the file

These positioning methods are useful for files opened in binary mode However, it does not make much sense to use them for text files or particularly for devices In text mode, conversions of LF <=> CR/LF prevent the methods from working correctly

䊐 Determining Positions in a File

The position of records in a files is easy to compute if all the records in the file are the same length Given that sizeis the length of a record

0L, size, 2*size,

are the positions of the first, second, third records, and so on

If you are working with variable length records, you cannot exactly compute their positions To enable random access you therefore need to store the positions of the

records in a separate structure, a so-called index.

The index stores pairs of keys and record positions, so-called index entries in a file A

key, a social security number, or customer id, for example, must uniquely identify a record If the index is sorted, the position that correlates to the required key can be quickly found using the binary search algorithm

TheIndexEntry class, used to represent an index entry, is shown opposite The class comprises methods for reading and writing an index entry at the current file position or

at any given position The appropriate file stream is passed as an argument to the method

Trang 6

644 C H A P T E R 2 9 M O R E A B O U T F I L E S

// index.h: (continued) // Adds the definition of an index //

-#include <string>

class IndexFile

{

private:

fstream index;

string name; // Filename of index

public:

IndexFile(const string& s);

~IndexFile() { index.close(); }

void insert( long key, long pos);

long search( long key);

void retrieve(IndexEntry& entry, long pos );

};

// index.cpp: (continued) // Adds methods of class IndexFile //

-IndexFile::IndexFile(const string& file)

{ ios::openmode mode = ios::in | ios::out

| ios::binary;

index.open(file.c_str(), mode);

if(!index) // If the file does not exist {

index.clear();

mode |= ios::trunc;

index.open(file.c_str(), mode);

if(!index) return;

} else name = file;

}

//

FILE STATE

Representing an index

Constructor of class IndexFile

Trang 7

䊐 State Flags

A file stream can assume various states, for example, when it reaches the end of a file and cannot continue reading A file operation can also fail if a file cannot be opened, or if a block is not transferred correctly

Theiosclass uses state flags to define the various states a file can assume Each state flag corresponds to a single bit in a status-word, which is represented by the iostate

type in the iosclass The following state flags exist:

■ ios::eofbit end of file reached

■ ios::failbit last read or write operation failed

■ ios::badbit an irrecoverable error occurred

■ ios::goodbit the stream is ok, e.g no other state flag is set

The “flag” ios::goodbitis an exception to the rule since it is not represented by a single bit, but by the value 0 if no other flag has been set In other words a status-word has the value ios::goodbitif everything is fine!

䊐 Discovering and Changing the State

There are multiple methods for discovering and modifying the status of a stream A method exists for each state flag; these are eof(),fail(),bad(), and good() They returntruewhen the corresponding flag has been raised This means you can discover the end of a file with the following statement:

The status-word of a stream can be read using the rdstate()method Individual flags can then be queried by a simple comparison:

The clear() method is available for clearing the status-word If you call clear()

without any arguments, all the state flags are cleared An argument of the iostatetype passed to clear()automatically becomes the new status-word for the stream

TheIndexFileclass, which uses a file to represent an index, is defined opposite The constructor for this class uses the clear()method to reset the failbit after an invalid attempt to open a non-existent file A new file can then be created

TheIndexFileclass comprises methods for inserting, seeking, and retrieving index entries, which we will be implementing later in this chapter

Trang 8

646 C H A P T E R 2 9 M O R E A B O U T F I L E S

// exceptio.h : Exception classes for file access //

-#ifndef _EXCEPTIO_H

#define _EXCEPTIO_H

#include <string>

#include <iostream>

using namespace std;

class FileError

{

private:

string filename;

public:

FileError( const string& file) : filename(file){ } string getName() const{ return filename; }

};

class OpenError : public FileError

{

public:

OpenError( const string& file):FileError(file){ } };

class ReadError : public FileError

{

public:

ReadError( const string& file):FileError(file){ } };

class WriteError : public FileError

{

public:

WriteError(const string& file):FileError(file){ } };

#endif

EXCEPTION HANDLING FOR FILES

Defining your own exception classes

Trang 9

䊐 Implementing Your Own Exception Handling

You can exploit the error tracking options that state flags give you to implement your own exception handling for files For example, a method that reads records from a file can throw an exception when the state flag ios::eofis raised, that is, when the end of the file is reached

The opposite page shows typical exception classes organized in a hierarchy that can be used to represent error conditions on opening, reading from, and writing to a file In each case the file name is saved for evaluation by the exception handler

䊐 Standard Exception Handling for Streams

C++ also provides standard exception handling for streams You can use the excep-tions() method to specify the flags in the status-word of a stream that will cause exceptions to be thrown

Theexceptions()method is defined in the ios stream base class The method expects one or multiple state flags separated by the |sign An exception is then thrown for the flags specified

Example: ifstream ifstrm("account.fle");

fstrm.exceptions(ios::failbit | ios::badbit);

On accessing the fstrm stream an exception is thrown if either one of the flags

ios::failbitorios::badbitis raised The operation that caused the error is then terminated and the state flags are cleared by a call to clear(rdstate());

The exception thrown here is of a standard exception class, failure This type is defined as a public element in the iosbase class and comprises the virtual method

what()that returns a C string containing the cause of the error The exception handler will normally send the string to standard error output

You can call exceptions()without any arguments to discover the state flags in a status-word of a stream that can cause an exception to be thrown If a bit is set in the return value of the exceptions()method, an appropriate exception will be thrown whenever this error occurs

if( except & ios::eofbit)

This statement uses a bitwise AND operator to ascertain whether an exception is thrown when end-of-file is reached

Trang 10

648 C H A P T E R 2 9 M O R E A B O U T F I L E S

// account.h : Defines the classes // Account, DepAcc, and SavAcc // with virtual read and write methods // -//

enum TypeId { ACCOUNT, DEP_ACC, SAV_ACC };

class Account {

private: // Data members: as previously defined public: // Constructor, access methods

virtual TypeId getTypeId() const { return ACCOUNT;} virtual ostream& write(ostream& fs) const;

virtual istream& read(istream& fs);

};

class DepAcc : public Account

{ // Data members, constructor,

TypeId getTypeId() const { return DEP_ACC; } ostream& write(ostream& fs) const;

istream& read(istream& fs);

};

class SavAcc: public Account

{ // Data members, constructor,

TypeId getTypeId() const { return SAV_ACC; } ostream& write(ostream& fs) const;

istream& read(istream& fs);

};

// account.cpp: Implements the methods

//

-#include "account.h"

ostream& DepAcc::write(ostream& os) const

{ if(!Account::write(os)) return os;

os.write((char*)&limit, sizeof(limit) );

os.write((char*)&deb, sizeof(deb) );

return os;

}

istream& DepAcc::read(istream& is)

{ if(!Account::read(is)) return is;

is.read((char*)&limit, sizeof(limit) );

is.read((char*)&deb, sizeof(deb));

return is;

} //

PERSISTENCE OF POLYMORPHIC OBJECTS

The methods read() and write() of class DepAcc

Ngày đăng: 06/07/2014, 17:21

TỪ KHÓA LIÊN QUAN