Давайте пока забудем про OutOfRange. Я может пока вообще удалю этот пример до лучших времён. В книге был пример с проверками файла на открытие чтение и т.д. А OutOfRange это я уже развил, а пример оказался неудачный
Теперь о файлах и собственных классах исключений
Если файл не открывается, то выбрасывается исключение FileOpenError с текстом, к примеру:
Error: unable to open the file "input.txt" in the "readData()"
Если из файла невозможно прочитать, то - FileReadError с тектом:
Error: unable to read the file "input.txt" in the "readData()"
Если диск переполнен и невозможно записать, то - FileWriteError с текстом:
Error: unable to write to the file "input.txt" in the "readData()"
Все выше перечисленные исключения наследуются от FileError, поэтому мы можем все три исключения отлавливать так:
C++ (Qt)
try {
// ...
}
catch ( const FileError &e ) {
std::cerr << e.what( ) << std::endl;
return 1;
} catch ( ... ) {
std::cerr << "Error: unknown exception" << std::endl;
return 1;
}
Исключение EmptyArgument выбрасывается, когда входные данные пустые и наследуется от LogicError
Следующий пример читает имена и фамилии из файла, заполняет массив объектов типа Person и выводит имена на экран:
main.cpp
C++ (Qt)
#include <iostream>
#include <vector>
#include <QString>
#include "freeFunctions.h"
#include "Person.h"
int main( )
{
// Person array for saving
Person david( "David", "White");
Person ivan( "Ivan", "Green" );
std::vector<Person> persons;
persons.push_back( david );
persons.push_back( ivan );
try {
// Parse the person array to the string content
QString content;
parsePersonsToStrContent( persons, content );
// Save the string content to the file
QString fileName = "file.txt";
writeData( fileName, content );
// Read the string content from the file
QString readContent;
readData( fileName, readContent );
// Parse the string content to the person array
std::vector<Person> readPersons;
parseContentToPersons( readContent, readPersons );
// Print the person array on the screen
printData( readPersons );
} catch ( const LogicError &e ) {
std::cerr << e.what( ) << std::endl;
return 1;
} catch ( const FileError &e ) {
std::cerr << e.what( ) << std::endl;
return 1;
} catch ( ... ) {
std::cerr << "Error: unknown exception" << std::endl;
return 1;
}
return 0;
}
Person.h
C++ (Qt)
#ifndef PERSON_H
#define PERSON_H
#include <QString>
class Person {
public:
Person( const QString &firstName = "",
const QString &lastName = "" ) :
m_firstName( firstName ),
m_lastName( lastName )
{
}
QString firstName( ) const
{
return m_firstName;
}
QString lastName( ) const
{
return m_lastName;
}
void setFirstName( const QString &firstName )
{
m_firstName = firstName;
}
void setLastName( const QString &lastName )
{
m_lastName = lastName;
}
private:
QString m_firstName;
QString m_lastName;
};
#endif // PERSON_H
freeFunctions.h
C++ (Qt)
#ifndef FREEFUNCTIONS_H
#define FREEFUNCTIONS_H
#include <vector>
#include <QString>
#include "FileOpenError.h"
#include "FileReadError.h"
#include "FileWriteError.h"
#include "EmptyArgument.h"
#include "Person.h"
void readData( const QString &fileName, QString &content )
throw ( EmptyArgument, FileOpenError, FileReadError );
void parseContentToPersons( const QString &content,
std::vector<Person> &persons )
throw ( EmptyArgument );
void parsePersonsToStrContent( const std::vector<Person> &persons,
QString &content)
throw ( EmptyArgument );
void writeData( const QString &fileName,
const QString &content )
throw ( EmptyArgument, FileOpenError, FileWriteError );
void printData( const std::vector<Person> &persons )
throw ( EmptyArgument );
#endif // FREEFUNCTIONS_H
freeFunctions.cpp
C++ (Qt)
#include <iostream>
#include <string>
#include <QFile>
#include <QRegExp>
#include <QTextStream>
#include <QDebug>
#include "freeFunctions.h"
void readData(const QString &fileName, QString &content )
throw ( EmptyArgument, FileOpenError, FileReadError )
{
std::string functionName = "readData()";
// Check argument
if ( fileName.isEmpty( ) ) {
throw EmptyArgument( functionName );
}
// Open the input file for reading
QFile file( fileName );
if( !file.open( QIODevice::ReadOnly ) ) {
throw FileOpenError( fileName.toStdString( ), functionName );
}
// Read the content from the file
QByteArray data = file.readAll( );
if ( data.isEmpty( ) ) {
throw FileReadError( fileName.toStdString( ), functionName );
}
content = QString( data );
}
void parseContentToPersons( const QString &content, std::vector<Person> &persons )
throw ( EmptyArgument )
{
std::string functionName = "parseContentToPersons()";
// Check the input argument
if ( content.isEmpty( ) ) {
throw EmptyArgument( functionName );
}
QRegExp regExp("(\\w+) (\\w+)");
int pos = 0;
while ( ( pos = regExp.indexIn( content, pos ) ) != -1 ) {
QString firstName = regExp.cap( 1 );
QString lastName = regExp.cap( 2 );
Person person( firstName, lastName );
persons.push_back( person );
pos += regExp.matchedLength( );
}
}
void parsePersonsToStrContent( const std::vector<Person> &persons,
QString &content)
throw ( EmptyArgument )
{
std::string functionName = "parsePersonsToStrContent()";
// Check the input argument
if ( persons.empty( ) ) {
throw EmptyArgument( functionName );
}
for ( std::size_t i = 0; i < persons.size( ); ++i ) {
QString firstName = persons[i].firstName( );
QString lastName = persons[i].lastName( );
QString line = QString( "%1 %2\n" ).arg( firstName ).arg( lastName );
content.append( line );
}
}
void writeData( const QString &fileName, const QString &content )
throw ( EmptyArgument, FileOpenError, FileWriteError )
{
std::string functionName = "writeData()";
// Check arguments
if ( fileName.isEmpty( ) || content.isEmpty( ) ) {
throw EmptyArgument( functionName );
}
// Open the output file for writing
QFile file( fileName );
if ( !( file.open( QIODevice::WriteOnly ) ) ) {
throw FileOpenError( fileName.toStdString( ), functionName );
}
// Write data to the output file
QTextStream stream( &file );
stream << content;
if ( stream.status() != QTextStream::Ok ) {
throw FileWriteError( fileName.toStdString( ), functionName );
}
}
void printData( const std::vector<Person> &persons )
throw ( EmptyArgument )
{
std::string functionName = "printData()";
// Check the input argument
if ( persons.empty( ) ) {
throw EmptyArgument( functionName );
}
// Print data
for ( std::size_t i = 0; i < persons.size( ); ++i ) {
std::cout << "First Name: " << persons[i].firstName( ).toStdString( ) << std::endl;
std::cout << "Last Name: " << persons[i].lastName( ).toStdString( ) << std::endl;
std::cout << std::endl;
}
}
FileError.h
C++ (Qt)
#ifndef FILEERROR_H
#define FILEERROR_H
#include <string>
#include <stdexcept>
class FileError : public std::runtime_error
{
public:
FileError( const std::string &fileName,
const std::string &functionName) :
std::runtime_error( "" ),
m_message( "" ),
m_fileName( fileName ),
m_functionName( functionName )
{
}
virtual ~FileError( ) throw( )
{
}
virtual const char *what() const throw( )
{
return m_message.c_str( );
}
std::string message( ) const
{
return m_message;
}
protected:
std::string m_message;
std::string m_fileName;
std::string m_functionName;
};
#endif // FILEERROR_H
FileOpenError.h
C++ (Qt)
#ifndef FILEOPENERROR_H
#define FILEOPENERROR_H
#include <string>
#include "FileError.h"
class FileOpenError : public FileError {
public:
FileOpenError( const std::string &fileName,
const std::string &functionName) :
FileError( fileName, functionName )
{
m_message = "Error: unable to open the file \"" +
m_fileName + "\" in the function \"" +
m_functionName + "\"";
}
};
#endif // FILEOPENERROR_H
FileReadError.h
C++ (Qt)
#ifndef FILEREADERROR_H
#define FILEREADERROR_H
#include <string>
#include "FileError.h"
class FileReadError : public FileError {
public:
FileReadError( const std::string &fileName,
const std::string &functionName ) :
FileError( fileName, functionName )
{
m_message = "Error: unable to read the file \"" + m_fileName +
"\" in the function \"" + m_functionName + "\"";
}
};
#endif // FILEREADERROR_H
FileWriteError.h
C++ (Qt)
#ifndef FILEWRITEERROR_H
#define FILEWRITEERROR_H
#include <string>
#include "FileError.h"
class FileWriteError : public FileError {
public:
FileWriteError( const std::string &fileName,
const std::string &functionName ) :
FileError( fileName, functionName )
{
m_message = "Error: unable to write to the file " +
m_fileName + " in the function " + m_functionName;
}
};
#endif // FILEWRITEERROR_H
EmptyArgument.h
C++ (Qt)
#ifndef EMPTYARGUMENT_H
#define EMPTYARGUMENT_H
#include <string>
#include "LogicError.h"
class EmptyArgument : public LogicError {
public:
EmptyArgument( const std::string &functionName ) :
LogicError( functionName )
{
m_message = "Error: empty argument in the "
"function " + m_functionName;
}
};
#endif // EMPTYARGUMENT_H
LogicError.h
C++ (Qt)
#ifndef LOGICERROR_H
#define LOGICERROR_H
#include <string>
#include <stdexcept>
class LogicError : public std::logic_error
{
public:
LogicError( const std::string &functionName ) :
std::logic_error( "" ),
m_functionName( functionName ),
m_message( "" )
{
}
virtual ~LogicError( ) throw( )
{
}
virtual const char *what( ) const throw( )
{
return m_message.c_str( );
}
std::string message( ) const
{
return m_message;
}
protected:
std::string m_functionName;
std::string m_message;
};
#endif // LOGICERROR_H