Binary File Reading in C ++

1

Good morning.

I'm trying to do a read of structs that I've inserted into a binary file, but it's giving error at the time of reading.

Here is the code for the read function:

void lerRegistros(char* file_name)
{
    ifstream entrada;
    entrada.open(file_name, ios::binary);

    if ( entrada )
    {
        entrada.seekg(0, entrada.end);
        int tam = entrada.tellg();
        entrada.seekg(0, entrada.beg);

        int numero_registros = tam / sizeof(registro);

        registro* vetor_registros = new registro[numero_registros];

        for (int i = 0; i < numero_registros; i++) 
        {
            entrada.read((char*)(&vetor_registros[i]), sizeof(registro));         
        }

        entrada.close();

        for ( int i = 0; i < numero_registros; ++i )
        {   
            cout << "Nome da banda: " << vetor_registros[i].nome << endl;
            cout << "Numero de integrantes: " << vetor_registros[i].numero_integrantes << endl;
            cout << "Estilo: " << vetor_registros[i].estilo << endl;
            cout << "Ano de criacao: " << vetor_registros[i].ano_criacao << endl;
            cout << "Melhor hit: " << vetor_registros[i].musica_famosa << endl;
            cout << endl;
        }

        vetor_registros = NULL;
        delete[] vetor_registros;
    }
    else
    {
        cout << "Erro na leitura do arquivo!";
    }

    return;
}

In the program, I ask for the file name to read the records and I pass that name to the read function. The strangest thing is that if I run the program without closing it, reading is done normally after each insertion of a new record. But if I close the program and open it again, and try to read from the same file that was already created there is an error reading and the program closes on time. If anyone knows what that can be, I appreciate it.

Here is the structure definition:

struct banda_rock 
{
    string nome;
    int numero_integrantes;
    string estilo;
    int ano_criacao;
    string musica_famosa;
};

And below is the code that writes to the file and calls the function "readRegister". In the "readRegistry" function, I put a "register" vector, but it was just to simplify the code, actually it's a "band_rock" vector, which is the name of the struct type I created.

int quant = 0;
char* file_name;

banda_rock* ptrcatalogo;

cout << endl << "Digite a quantidade de bandas : ";
cin >> quant;

file_name = new char[100];

cout << "Digite o nome do arquivo a ser armazenado as bandas (com o extensao) : ";
cin >> file_name;
cin.ignore();

ptrcatalogo = new banda_rock[quant];

ofstream salvar_bandas; 
salvar_bandas.open(file_name, ios::binary|ios::app);

inserir_cadastro(quant, ptrcatalogo);

for (int i = 0; i < quant; i++) 
{
    salvar_bandas.write(reinterpret_cast<const char*> (&ptrcatalogo[i]), sizeof(banda_rock));                 
}

ptrcatalogo = NULL;
delete[] ptrcatalogo;

salvar_bandas.close();

lerRegistros(file_name);

file_name = NULL;
delete file_name;
    
asked by anonymous 15.01.2018 / 18:40

2 answers

1

Note:

I wrote a code based on what you had said, that you wanted the code to do. to better demonstrate the answer, in terms of C ++ functionalities.

Details:

You said that you are programming in C ++ but you are using a style similar to C not that it is wrong, but for example you do not need to use naked pointers to manipulate the struct you created, or pass a const char * to the read function, but this does not come to the case of the question, what I wanted to tell you with this is for you to study the "functionalities" that the language offers you, rather than trying to do it the old way.

Answer:

I believe in your code what is wrong with the read function, is the use of read the way you used it,

  

input.read ((char *) (& vector_registers [i]), sizeof (record));

And also after the for loop where you display the data, you are setting vector_registers to NULL before deleting it:

  

vector_registers = NULL;
  delete [] vector_registers;

where the right one would be:

  

delete [] vector_registers;   vector_registers = nullptr;

Code:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>

struct banda_rock 
{
    std::string nome;
    int numero_integrantes;
    std::string estilo;
    int ano_criacao;
    std::string musica_famosa;
};

bool write( const std::string& file_name, const std::vector<banda_rock>& v_registers ); 
std::vector< banda_rock > read( const std::string& file_name );
void insert( const size_t& num_registers, std::vector<banda_rock>& v_registers );

int main()
{ 
    //quant deve ser size_t por que já que você tem a intenção de expressar a
    //quantidade de algo, e essa quantidade não pode ser negativa
    //(size_t só aceita valores positivos e o 0( no seu caso você não precisa do 0) )
    size_t quant = 0;
    std::string file_name;
    std::vector< banda_rock > v_catalogo;


    //Caso o que a pessoa digite não seja um número ou um numero menor que zero
    if( quant == 0 )
    {
        std::cout << "\nDigite a quantidade de bandas : ";
        std::cin >> quant; 
        while( std::cin.fail() )
        { 
            std::cin.clear( std::ios::goodbit );
            std::cin.ignore(); 
            std::cin >> quant; 

        }
    }
    if( quant > 0 )
    {
        std::cout << "Digite o nome do arquivo a ser armazenado as bandas (com a extensao) : ";
        std::cin >> file_name; 
        while( std::cin.fail() )
        { 
            std::cin.clear( std::ios::goodbit );
            std::cin.ignore(); 
            std::cin >> file_name;
        }
    }       


    //chama a função que vai popular o vetor
    insert( quant, v_catalogo );

    //escreve  arquivo
    if( write( file_name, v_catalogo ) )
    {
        //se a operação de escrita obteve sucesso
        v_catalogo.clear();
        v_catalogo.shrink_to_fit();
        v_catalogo = read( file_name );
    }
    else{ std::cout << "\nNão foi possivel escrever no arquivo." << std::endl; }

    for ( size_t i = 0; i < v_catalogo.size(); i++) 
    {
        std::cout << "\tNome: " << v_catalogo[ i ].nome << '\n' 
                  << "\tIntegrantes: " << v_catalogo[ i ].numero_integrantes << '\n' 
                  << "\tEstilo: " << v_catalogo[ i ].estilo << '\n'
                  << "\tAno de criação: " << v_catalogo[ i ].ano_criacao << '\n'
                  << "\tMúsica Famosa: " << v_catalogo[ i ].musica_famosa << "\n\n";
    }

    return 0;
}

bool write( const std::string& file_name, const std::vector<banda_rock>& v_registers )
{
    if( v_registers.empty() ){ return false; }

    std::ofstream out; 
    out.open( file_name, std::ios::binary|std::ios::app );
    if( !out.is_open() ){ out.close(); return false; }
    else
    {
        for ( size_t i = 0; i < v_registers.size(); i++) 
        {
            //o # pode servir para posteriormente para você contar quantos 
            //registros você têm (fica a seu critério usá-lo ou não)
            out << '#' << ' ' 
                << v_registers[ i ].nome << ' ' 
                << v_registers[ i ].numero_integrantes << ' ' 
                << v_registers[ i ].estilo << ' '
                << v_registers[ i ].ano_criacao << ' '
                << v_registers[ i ].musica_famosa << '\n';            
        }
    }

    out.close();
    return true;
}

std::vector< banda_rock > read( const std::string& file_name )
{
    std::ifstream in;
    size_t quant = 0;
    char ch_aux;

    in.open(file_name, std::ios::binary);
    if ( !in.is_open() ){ in.close(); }
    else
    {
        while( !in.eof() )
        {
            in.get( ch_aux );
            if( ch_aux == '#' ){ quant++; }
        }
    }    
    in.close();

    std::vector<banda_rock> v_registers;
    v_registers.resize( quant );

    in.open(file_name, std::ios::binary);
    if ( !in.is_open() ){ in.close(); }
    else
    {
        for( size_t i = 0; i < v_registers.size(); i++ )
        {
                in.ignore( 1, '#' );
                in >> v_registers[ i ].nome 
                   >> v_registers[ i ].numero_integrantes
                   >> v_registers[ i ].estilo
                   >> v_registers[ i ].ano_criacao
                   >> v_registers[ i ].musica_famosa;
        } 
    }    
    in.close();

    return v_registers;

}

void insert( const size_t& num_registers, std::vector<banda_rock>& v_registers )
{
    v_registers.resize( num_registers );

    std::cout << "insira os dados da banda:" << std::endl;
    for( size_t i = 0; i < v_registers.size(); i++ )
    {
        std::cout << " Nome da banda [" << i + 1 << "]: ";
        std::cin >> v_registers[ i ].nome;
        while( std::cin.fail() )
        { 
            std::cout << "\tpor favor digite o nome da banda [" << i + 1 << "]." << std::endl;
            std::cin.clear( std::ios::goodbit ); 
            std::cin.ignore();  
            std::cin >> v_registers[ i ].nome;
        }

        std::cout << " Número de integrantes da banda [" << i + 1 << "]: ";
        std::cin >> v_registers[ i ].numero_integrantes;
        while( std::cin.fail() )
        { 
            std::cout << "\tpor favor digite o número de integrantes da banda [" << i + 1 << "]." << std::endl; 
            std::cin.clear( std::ios::goodbit ); 
            std::cin.ignore(); 
            std::cin >> v_registers[ i ].numero_integrantes;
        }

        std::cout << " Estilo da banda [" << i + 1 << "]: ";
        std::cin >> v_registers[ i ].estilo;
        while( std::cin.fail() )
        { 
            std::cout << "\tpor favor digite o estilo da banda [" << i + 1 << "].";                                     
            std::cin.clear( std::ios::goodbit ); 
            std::cin.ignore();
            std::cin >> v_registers[ i ].estilo;
        }

        std::cout << " Ano de criação da banda [" << i + 1 << "]: ";
        std::cin >> v_registers[ i ].ano_criacao;
        while( std::cin.fail() )
        { 
            std::cout << "\tpor favor digite o ano de criação da banda [" << i + 1 << "]."; 
            std::cin.clear( std::ios::goodbit ); 
            std::cin.ignore(); 
            std::cin >> v_registers[ i ].ano_criacao;
        }

        std::cout << " Musica Conhecida da banda[" << i + 1 << "]: ";
        std::cin >> v_registers[ i ].musica_famosa;
        while( std::cin.fail() )
        { 
            std::cout << "\tpor favor digite uma música conhecida da banda [" << i + 1 << "].";
            std::cin.clear( std::ios::goodbit );  
            std::cin.ignore(); 
            std::cin >> v_registers[ i ].musica_famosa;
        }

    }
}
    
16.01.2018 / 15:00
0

You have the following problem: In c ++ the binary files do not accept dynamic variables like string s and vector . You need to read / write the file as a char vector, so use the reinterpret_cast function:

arquivo.write(reinterpret_cast  <const char *> 
(&variavel),sizeof(tipo_dado_variavel))


arquivo.read(reinterpret_cast<char *> (&variavel),
sizeof(tipo_dado_variavel))

* The >> operator does not work for binary streams, it must be arquivo.read/write itself.

    
16.08.2018 / 00:14