Класс для чтения/записи CSV файлов. Подробнее...
#include <loaders/csv_file.h>
Открытые члены | |
| void | OpenFile (const char *FilePath) |
| void | OpenFile (const std::string &FilePath) |
| bool | ReadRecord (CSVReadable *Readable, const std::size_t MODE=0) |
| void | ReadHeader (const std::size_t MODE=0) |
| std::size_t | GetHeaderItemsCount (void) |
| nitro::BinaryData & | GetHeaderItem (std::size_t i) |
| template<class cont > | |
| bool | ReadRecord (cont &Container, const std::size_t MODE=0) |
| template<class cont > | |
| void | ReadAllRecords (cont &Container, const std::size_t MODE=0) |
| void | AppendRecord (CSVWritable *Writable, const std::size_t MODE=0) |
| template<class cont > | |
| void | AppendRecord (cont &Container, const std::size_t MODE=0) |
| template<class cont > | |
| void | AppendAllRecords (cont &Container, const std::size_t MODE=0) |
| void | CloseFile (void) |
| virtual | ~CSVFile () |
Открытые статические члены | |
| static void | SetReadBufferSize (std::size_t ReadBufferSize) |
Закрытые данные | |
| nitro::FileAbstraction | FileStream |
| std::vector< nitro::BinaryData > | Header |
Класс для чтения/записи CSV файлов.
См. определение в файле csv_file.h строка 193
| nitro::CSVFile::~CSVFile | ( | ) | [virtual] |
Деструктор.
См. определение в файле csv_file.cpp строка 494
Перекрестные ссылки CloseFile().
{
try
{
CloseFile();
}
catch( ... )
{
}
}

| void nitro::CSVFile::AppendAllRecords | ( | cont & | Container, | |
| const std::size_t | MODE = 0 | |||
| ) |
Функция записи записей.
| Container | - Тот или иной контейнер содержащий объекты nitro::BinaryData. | |
| MODE | - Режим чтения записей. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.h строка 632
Перекрестные ссылки AppendRecord(), nitro::exception::code() и nitro::exception::what().
{
try
{
typedef typename cont::iterator IterType;
for( IterType i( Container.begin() ) ; i != Container.end() ; ++i )
{
AppendRecord( *i , MODE );
}
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::AppendAllRecords( cont & Container , const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::AppendAllRecords( cont & Container , const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::AppendRecord | ( | CSVWritable * | Writable, | |
| const std::size_t | MODE = 0 | |||
| ) |
Функция записи одной записи.
| Writable | - Интерфейс для сохранения данных в файле из объекта. | |
| MODE | - Режим сохранения записей. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 355
Перекрестные ссылки nitro::BinaryData::AppendData(), nitro::exception::code(), nitro::CSV_AUTO_ESCAPE(), nitro::FA_FILE_BEGIN, nitro::FA_FILE_END, FileStream, nitro::BinaryData::GetBuffer(), nitro::BinaryData::GetBufferLength(), nitro::CSVWritable::GetField(), nitro::CSVWritable::GetFieldCount(), nitro::BinaryData::GetOccuranceCount(), nitro::FileAbstraction::Read(), nitro::BinaryData::Reserve(), nitro::FileAbstraction::Seek(), nitro::FileAbstraction::Tell(), nitro::exception::what() и nitro::FileAbstraction::Write().
Используется в AppendAllRecords() и AppendRecord().
{
try
{
std::size_t FilePosition( FileStream.Tell() );
// \~russian сначала считаем сколько нам понадобится байт
// \~english count how many bytes do we need
std::size_t BytesCount( 0 );
// \~russian смотрим что в конце файла
// \~english what do we have at the end of the file?
FileStream.Seek( 0 , FA_FILE_END );
std::size_t EndOfFilePosition( FileStream.Tell() );
FileStream.Seek( EndOfFilePosition - 2 , FA_FILE_BEGIN );
char EndOfFile[ 2 ];
FileStream.Read( EndOfFile , 2 );
bool PrependCRLF( false );
if( EndOfFile[ 0 ] != '\r' || EndOfFile[ 1 ] != '\n' )
{
PrependCRLF = true;
BytesCount += 2;
}
const char * Buffer;
std::size_t BufferSize;
int Tmp;
// \~russian длина полей (нужно ли обрамлять поле кавычками)
// \~english fields length (should be the field bounded by braces)
for( std::size_t i( 0 ) ; i < Writable->GetFieldCount() ; i++ )
{
Writable->GetField( i , Buffer , BufferSize , MODE );
BytesCount += BufferSize;
if( MODE & CSV_AUTO_ESCAPE )
{
Tmp = nitro::BinaryData::GetOccuranceCount( Buffer , BufferSize , "\"" , 1 );
if( Tmp != 0 )
{
BytesCount += 2 + Tmp;
}
}
}
// \~russian запятые
// \~english commas
BytesCount += Writable->GetFieldCount() - 1;
// \~russian добавляем CRLF
// \~english appending CRLF
BytesCount += 2;
nitro::BinaryData Data;
if( PrependCRLF )
{
Data.Reserve( BytesCount + 2 );
Data.AppendData( "\r\n" );
}
else
{
Data.Reserve( BytesCount );
}
for( std::size_t i( 0 ) ; i < Writable->GetFieldCount() ; i++ )
{
Writable->GetField( i , Buffer , BufferSize , MODE );
Tmp = 0;
if( MODE & CSV_AUTO_ESCAPE )
{
Tmp = nitro::BinaryData::GetOccuranceCount( Buffer , BufferSize , "\"" , 1 );
}
if( Tmp != 0 )
{
Data.AppendData( '"' );
}
for( std::size_t j( 0 ) ; j < BufferSize ; j++ )
{
if( Buffer[ j ] == '"' && ( MODE & CSV_AUTO_ESCAPE ) )
{
Data.AppendData( '"' );
}
Data.AppendData( Buffer[ j ] );
}
if( Tmp != 0 )
{
Data.AppendData( '"' );
}
if( i < Writable->GetFieldCount() - 1 )
{
Data.AppendData( ',' );
}
else
{
Data.AppendData( "\r\n" , 2 );
}
}
FileStream.Write( Data.GetBuffer() , Data.GetBufferLength() );
FileStream.Seek( FilePosition , FA_FILE_BEGIN );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::AppendRecord( CSVWritable * Writable , const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::AppendRecord( CSVWritable * Writable , const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::AppendRecord | ( | cont & | Container, | |
| const std::size_t | MODE = 0 | |||
| ) |
Функция записи одной записи.
| Container | - Тот или иной контейнер содержащий объекты nitro::BinaryData. | |
| MODE | - Режим чтения записей. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.h строка 594
Перекрестные ссылки AppendRecord(), nitro::exception::code() и nitro::exception::what().
{
try
{
class CSVRecordWriter:public CSVWritable{
cont * Container;
public:
CSVRecordWriter( cont * theContainer )
{
Container = theContainer;
}
virtual void GetField( const std::size_t & FieldCursor , const char * & Buffer , std::size_t & BufferSize , const std::size_t & MODE = 0 )
{
Buffer = ( * Container )[ FieldCursor ].GetBuffer();
BufferSize = ( * Container )[ FieldCursor ].GetBufferLength();
}
virtual std::size_t GetFieldCount( void )
{
return( Container->size() );
}
};
CSVRecordWriter Writer( & Container );
return( AppendRecord( ( CSVWritable * ) & Writer , MODE ) );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::AppendRecord( cont & Container , const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::AppendRecord( cont & Container , const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::CloseFile | ( | void | ) |
Закрытие файла.
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 478
Перекрестные ссылки nitro::FileAbstraction::Close(), nitro::exception::code(), FileStream и nitro::exception::what().
Используется в ~CSVFile().
{
try
{
FileStream.Close();
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::CloseFile( void )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::CloseFile( void )::An error occured" ) , 1 ) );
}
}

| nitro::BinaryData & nitro::CSVFile::GetHeaderItem | ( | std::size_t | i | ) |
Функция возвращает элемент заголовка.
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 339
Перекрестные ссылки nitro::exception::code(), Header и nitro::exception::what().
{
try
{
return( Header[ i ] );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::GetHeaderItem( std::size_t i )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::GetHeaderItem( std::size_t i )::An error occured" ) , 1 ) );
}
}

| std::size_t nitro::CSVFile::GetHeaderItemsCount | ( | void | ) |
Функция возвращает количество элементов в заголовке.
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 323
Перекрестные ссылки nitro::exception::code(), Header и nitro::exception::what().
{
try
{
return( Header.size() );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::GetHeaderItemsCount( void )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::GetHeaderItemsCount( void )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::OpenFile | ( | const char * | FilePath | ) |
Открытие файла на чтение.
| FilePath | - Путь к открываемому файлу. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 43
Перекрестные ссылки nitro::exception::code(), nitro::FA_FILE_BINARY, nitro::FA_FILE_READ, nitro::FA_FILE_WRITE, FileStream, nitro::FileAbstraction::Open() и nitro::exception::what().
Используется в OpenFile().
{
try
{
FileStream.Open( FilePath , nitro::FA_FILE_BINARY | nitro::FA_FILE_READ | nitro::FA_FILE_WRITE );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::OpenFile( const char * FilePath )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::OpenFile( const char * FilePath )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::OpenFile | ( | const std::string & | FilePath | ) |
Открытие файла на чтение.
| FilePath | - Путь к открываемому файлу. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 59
Перекрестные ссылки nitro::exception::code(), OpenFile() и nitro::exception::what().
{
try
{
OpenFile( FilePath.c_str() );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::OpenFile( const std::string & FilePath )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::OpenFile( const std::string & FilePath )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::ReadAllRecords | ( | cont & | Container, | |
| const std::size_t | MODE = 0 | |||
| ) |
Функция чтения всех записей.
| Container | - Тот или иной контейнер содержащий объекты контейнеры с объектами nitro::BinaryData. | |
| MODE | - Режим чтения записей. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.h строка 564
Перекрестные ссылки nitro::exception::code(), ReadRecord() и nitro::exception::what().
{
try
{
typedef typename cont::value_type FieldType;
FieldType CSVRecord;
bool EndOfFile( false );
do
{
EndOfFile = ReadRecord( CSVRecord , MODE );
* ( std::back_inserter( Container ) ) = CSVRecord;
CSVRecord.erase( CSVRecord.begin() , CSVRecord.end() );
}
while( EndOfFile == false );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::ReadAllRecords( cont & Container , const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::ReadAllRecords( cont & Container , const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::ReadHeader | ( | const std::size_t | MODE = 0 |
) |
Функция чтения заголовка.
| MODE | - Режим чтения заголовка. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 307
Перекрестные ссылки nitro::exception::code(), Header, ReadRecord() и nitro::exception::what().
{
try
{
ReadRecord( Header , MODE );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::ReadHeader( const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::ReadHeader( const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| bool nitro::CSVFile::ReadRecord | ( | cont & | Container, | |
| const std::size_t | MODE = 0 | |||
| ) |
Функция чтения одной записи.
| Container | - Тот или иной контейнер содержащий объекты nitro::BinaryData. | |
| MODE | - Режим чтения записей. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.h строка 529
Перекрестные ссылки nitro::exception::code(), ReadRecord() и nitro::exception::what().
{
try
{
class CSVRecordReader:public CSVReadable{
cont * Container;
typedef typename cont::value_type FieldType;
public:
CSVRecordReader( cont * theContainer )
{
Container = theContainer;
}
virtual void AddField( const char * Buffer , const std::size_t & BufferSize )
{
std::back_inserter( * Container ) = FieldType();
Container->back().AppendData( Buffer , BufferSize );
}
};
CSVRecordReader Reader( & Container );
return( ReadRecord( ( CSVReadable * ) & Reader , MODE ) );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::ReadRecord( cont & Container , const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::ReadRecord( cont & Container , const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| bool nitro::CSVFile::ReadRecord | ( | CSVReadable * | Readable, | |
| const std::size_t | MODE = 0 | |||
| ) |
Функция чтения одной записи.
| Readable | - Интерфейс для сохранения данных из файла в объект. | |
| MODE | - Режим чтения записей. |
| nitro::exception | Кидает исключение этого типа с описанием ошибки. |
См. определение в файле csv_file.cpp строка 75
Перекрестные ссылки nitro::ADD_FIELD(), nitro::CSVReadable::AddField(), nitro::BinaryData::AppendData(), nitro::exception::code(), nitro::CSV_AUTO_ESCAPE(), nitro::CSV_FILE_READ_BUFFER_SIZE(), nitro::END_QUOTED_FIELD(), nitro::END_RECORD(), nitro::FA_FILE_BEGIN, FileStream, nitro::BinaryData::GetBuffer(), nitro::BinaryData::GetBufferLength(), nitro::QUOTE_WAS_FOUND(), nitro::FileAbstraction::Read(), nitro::READ_DATA(), nitro::BinaryData::ReplaceBuffer(), nitro::FileAbstraction::Seek(), nitro::START_FIELD(), nitro::FileAbstraction::Tell(), nitro::TRY_READ_NEXT() и nitro::exception::what().
Используется в ReadAllRecords(), ReadHeader() и ReadRecord().
{
try
{
std::size_t FilePosition;
std::size_t ReadBytes;
// saving this value on stack to avoid 'ass pain' debug in multy-threaded applications
const std::size_t ReadBufferSize( CSV_FILE_READ_BUFFER_SIZE );
char * Buffer( new char[ ReadBufferSize ] );
bool QFieldStart( false );
bool FieldStart( false );
std::size_t FieldStartCursor( 0 );
std::size_t State( START_FIELD );
std::size_t FieldRawSize( 0 );
do
{
FilePosition = FileStream.Tell();
ReadBytes = FileStream.Read( Buffer , ReadBufferSize );
for( std::size_t i( 0 ) ; i < ReadBufferSize + 1 && i < ReadBytes + 1 ; i++ )
{
if( ReadBytes == 0 || ( ReadBytes < ReadBufferSize && i == ReadBytes ) )
{
if( QFieldStart == true )
{
throw( nitro::exception( "Illegal sintax (quote was not found)" , 1 ) );
}
if( FieldStart == true )
{
State = ADD_FIELD;
}
}
else
{
if( i == ReadBufferSize || i == ReadBytes )
{
continue;
}
}
if( State == START_FIELD )
{
FieldRawSize = 0;
if( ( Buffer[ i ] >= 0x20 && Buffer[ i ] <= 0x21 ) ||
( Buffer[ i ] >= 0x23 && Buffer[ i ] <= 0x2b ) ||
( Buffer[ i ] >= 0x2d && Buffer[ i ] <= 0x7e ) || Buffer[ i ] == ',' )
{
FieldStart = true;
FieldStartCursor = FilePosition + i;
State = READ_DATA;
}
if( Buffer[ i ] == '"' )
{
FieldRawSize++;
QFieldStart = true;
FieldStartCursor = FilePosition + i;
State = READ_DATA;
continue;
}
}
if( State == READ_DATA )
{
FieldRawSize++;
if( Buffer[ i ] == '"' && QFieldStart == false )
{
throw( nitro::exception( "Illegal sintax (quote was found)" , 1 ) );
}
if( Buffer[ i ] == '\r' && QFieldStart == false )
{
FieldRawSize--;
State = ADD_FIELD;
}
if( Buffer[ i ] == '\n' && QFieldStart == false )
{
throw( nitro::exception( "Illegal sintax (LF was found)" , 1 ) );
}
if( Buffer[ i ] == '"' && QFieldStart == true )
{
if( i < ReadBytes - 1 )
{
State = QUOTE_WAS_FOUND;
continue;
}
else
{
State = ADD_FIELD;
}
}
if( Buffer[ i ] == ',' && FieldStart == true )
{
FieldRawSize--;
State = ADD_FIELD;
}
}
if( State == QUOTE_WAS_FOUND )
{
if( Buffer[ i ] == '"' )
{
FieldRawSize++;
State = READ_DATA;
continue;
}
if( Buffer[ i ] == ',' || Buffer[ i ] == '\r' )
{
State = ADD_FIELD;
}
else
{
throw( nitro::exception( "Can't end quoted field (1)'" , 1 ) );
}
}
if( State == END_QUOTED_FIELD )
{
if( Buffer[ i ] == ',' )
{
State = ADD_FIELD;
}
else
{
throw( nitro::exception( "Can't end quoted field (2)'" , 1 ) );
}
}
if( State == ADD_FIELD )
{
if( FieldRawSize > 0 )
{
nitro::BinaryData Data;
std::size_t Decreaser( 0 );
if( QFieldStart == true )
{
Decreaser = 1;
}
if( FieldStartCursor < FilePosition )
{
// data is stored in several buffers, so let's read it in memory
char * FieldValue( new char [ FieldRawSize - 2 * Decreaser ] );
FileStream.Seek( FieldStartCursor + Decreaser , FA_FILE_BEGIN );
FileStream.Read( FieldValue , FieldRawSize - 2 * Decreaser );
Data.AppendData( FieldValue , FieldRawSize - 2 * Decreaser );
FileStream.Seek( FilePosition + ReadBufferSize , FA_FILE_BEGIN );
delete [] FieldValue;
}
else
{
// data is stored in one buffer, so it is already in memory
std::size_t BufferOffset( FieldStartCursor + Decreaser - FilePosition );
Data.AppendData( Buffer + BufferOffset , FieldRawSize - 2 * Decreaser );
}
if( MODE & CSV_AUTO_ESCAPE )
{
nitro::BinaryData::ReplaceBuffer( Data , ( const char * )"\"\"" , ( const std::size_t )2 , ( const char * )"\"" , ( const std::size_t )1 );
}
Readable->AddField( Data.GetBuffer() , Data.GetBufferLength() );
}
else
{
Readable->AddField( "" , 0 );
}
QFieldStart = false;
FieldStart = false;
State = TRY_READ_NEXT;
}
if( State == TRY_READ_NEXT )
{
if( Buffer[ i ] == ',' )
{
State = START_FIELD;
}
if( Buffer[ i ] == '\r' )
{
State = END_RECORD;
continue;
}
}
if( State == END_RECORD )
{
if( Buffer[ i ] == '\n' )
{
// чтение закончено
State = START_FIELD;
FileStream.Seek( FilePosition + i + 1 , FA_FILE_BEGIN );
delete [] Buffer;
return( false );
}
else
{
throw( nitro::exception( "Can't find LF symbol" , 1 ) );
}
}
}
}
while( ReadBytes == ReadBufferSize );
delete [] Buffer;
return( true );
}
catch( nitro::exception e )
{
throw( nitro::exception( std::string( "CSVFile::ReadRecord( CSVReadable * Readable , const std::size_t MODE /* = 0 */ )::" ) + e.what() , e.code() ) );
}
catch( ... )
{
throw( nitro::exception( std::string( "CSVFile::ReadRecord( CSVReadable * Readable , const std::size_t MODE /* = 0 */ )::An error occured" ) , 1 ) );
}
}

| void nitro::CSVFile::SetReadBufferSize | ( | std::size_t | ReadBufferSize | ) | [static] |
Функция установки размера буффера чтения.
См. определение в файле csv_file.cpp строка 505
Перекрестные ссылки nitro::CSV_FILE_READ_BUFFER_SIZE().
{
CSV_FILE_READ_BUFFER_SIZE = ReadBufferSize;
}

Файловый поток.
См. определение в файле csv_file.h строка 514
Используется в AppendRecord(), CloseFile(), OpenFile() и ReadRecord().
std::vector< nitro::BinaryData > nitro::CSVFile::Header [private] |
Заголовок файла.
См. определение в файле csv_file.h строка 526
Используется в GetHeaderItem(), GetHeaderItemsCount() и ReadHeader().
1.6.1