Arquivo binário em c++ com cabecalho

1. Arquivo binário em c++ com cabecalho

Bruno
uNclear

(usa Slackware)

Enviado em 15/11/2016 - 22:02h

Olá galera, to precisando inserir um cabecalho e alguns objetos em um arquivo binário. Estou tentando inserir o cabecalho sempre no inicio do arquivo (o cabecalho sera a quantidade de objetos q tenho no arquivo). E queria inserir os objetos apartir da posiçao que o cabecalho esta.


void personagem::inserir(){
int cabecalho = 0;
ofstream arquivo;
if (!existeArquivo("warcraft.bat")){
cout << "O arquivo nao existia, foi necessario cria-lo" << endl;
criarArquivo("warcraft.bat");
}
cabecalho = lerCabecalho("warcraft.bat");
cabecalho++;
cout << "cabecalho :" << cabecalho << endl;
arquivo.seekp(0,ios::beg);
arquivo.write(reinterpret_cast<char*>(&cabecalho), sizeof(int));
arquivo.open("warcraft.bat", ios::binary | ios::out | ios::app);
arquivo.write((char *)this, sizeof(personagem));
arquivo.close();
}

so q desse modo o cabeçalho nao esta sendo sobreescrito na primeira posiçao do arquivo, ai na hora que vou usar a funçao lerCabecalho o valor smp vem outro e eu perco o valor real do cabecalho. Pelo que estou vendo usar ios::app com seekp parece dar bug.


  


2. Re: Arquivo binário em c++ com cabecalho

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/11/2016 - 08:35h

Pelo código que você mostrou, você não associa arquivo a nenhum nome de arquivo, seja durante a declaração/construção, seja chamando a função-membro open(), até depois de ter tentado gravar o cabeçalho. Assim sendo, parece-me razoável que o seekp() e o write() falhem.


3. Arquivo binário em c++ com cabecalho

Bruno
uNclear

(usa Slackware)

Enviado em 16/11/2016 - 10:36h

Você fala que eu tenho q passar o arquivo por parametro sempre e ficar retornando ele? Eu n posso simplismente declarar outro em outra função com o msm nome? Dei umas modificadas e ficou assim, so a impressao que nao esta completa e o cabecalho nao esta sendo inserido corretamente no inicio.


void personagem::inserir(){
static int cabecalho = 0;
ofstream arquivo("warcraft.bat", ios::binary | ios::app);
if (!arquivo){
cout << "O arquivo nao existia, foi necessario cria-lo" << endl;
criarArquivo("warcraft.bat");
}
cabecalho++;
cout << "cabecalho :" << cabecalho << endl;
arquivo.write((char *)this, sizeof(personagem));
arquivo.seekp(0);
arquivo.write((char*)(&cabecalho), sizeof(int));
arquivo.close();
}



void listagem(personagem p){
ifstream arquivo("warcraft.bat", ios::binary | ios::in);
if(!arquivo){
cerr << "O arquivo nao existe" << endl;
exit(EXIT_FAILURE);
}else{
while(arquivo && ! arquivo.eof()){
p.escreve();
arquivo.read((char *)&p, sizeof(personagem));
}
cout << "Cabecalho do arquivo: " << lerCabecalho("warcraft.bat") << endl;
}
}



int lerCabecalho(string nome){
ifstream arquivo(nome.c_str(), ios::binary | ios::in);
int cabecalho;
arquivo.read((char*)(&cabecalho), sizeof(int));
return cabecalho;
}

No fim da funçao listagem eu testo se o cabecalho foi reescrito corretamento no inicio do arquivo


4. Re: Arquivo binário em c++ com cabecalho

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/11/2016 - 12:40h

uNclear escreveu:

Você fala que eu tenho q passar o arquivo por parametro sempre e ficar retornando ele? Eu n posso simplismente declarar outro em outra função com o msm nome? Dei umas modificadas e ficou assim, so a impressao que nao esta completa e o cabecalho nao esta sendo inserido corretamente no inicio.

void personagem::inserir(){
static int cabecalho = 0;
ofstream arquivo("warcraft.bat", ios::binary | ios::app);


Essa linha aí em cima é que não existia.

No primeiro programa, você tinha colocado apenas “ofstream arquivo;”, o que criava um objeto do tipo std::ofstream mas não o ligava a nenhum arquivo. Essa ligação poderia ser feita posteriormente através da função-membro open(), mas você só chamava tal função depois de tentar -- e falhar, pelo fato de não haver arquivo ligado ao objeto -- duas operações que fariam a gravação do cabeçalho.

Do jeito como você fez agora, o objeto já é criado com uma ligação ao arquivo, pois você já especifica tal ligação no construtor do objeto.

Contudo, você abriu o arquivo com o modo append. Desse jeito, você força todas as operações de escrita a serem realizadas no fim do arquivo. Qualquer conteúdo anterior será preservado, e mesmo que você mova o ponteiro de gravação explicitamente, através da função-membro seekp(), o atributo append obrigará as gravações a ocorrerem no final (como se houvesse um seekp(0, ios_base::end); implícito antes de cada operação de escrita).

        if (!arquivo){
cout << "O arquivo nao existia, foi necessario cria-lo" << endl;
criarArquivo("warcraft.bat");


O que quer que a função criarArquivo faça, mesmo que seja bem sucedido, não afetará o objeto local arquivo. Em particular, agora que você forçou a haver uma ligação entre o objeto e um arquivo de fato, o programa só vai entrar neste pedaço do código se a criação do objeto, que inclui a associação ao arquivo, tiver falhado. Como, porém, a função criarArquivo() não mexe no objeto local arquivo, tal objeto continuará dissociado de qualquer arquivo real em disco e, desse modo, todas as operações que vierem abaixo serão inválidas.

        }
cabecalho++;
cout << "cabecalho :" << cabecalho << endl;
arquivo.write((char *)this, sizeof(personagem));


A gravação acima será feita ao final do arquivo.

        arquivo.seekp(0);
arquivo.write((char*)(&cabecalho), sizeof(int));


E esta gravação aqui também será feita ao final do arquivo.

        arquivo.close();
}



5. Arquivo binário em c++ com cabecalho

Bruno
uNclear

(usa Slackware)

Enviado em 16/11/2016 - 12:54h

Na função inserir eu posso tirar a funçao criarArquivo, pois do jeito q ta o programa nunca vai entrar no if, mas n entendi pq os comandos embaixo do if estao invalidos. E queria saber como eu posso inserir um numero sempre no inicio do arquivo, e inserir um objeto no resto do arquivo sem usar os parametros que sao utilizados junto com a funçao open, como exemplo o ios::app.


6. Re: Arquivo binário em c++ com cabecalho

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/11/2016 - 13:01h

uNclear escreveu:

Na função inserir eu posso tirar a funçao criarArquivo, pois do jeito q ta o programa nunca vai entrar no if, mas n entendi pq os comandos embaixo do if estao invalidos. E queria saber como eu posso inserir um numero sempre no inicio do arquivo, e inserir um objeto no resto do arquivo sem usar os parametros que sao utilizados junto com a funçao open, como exemplo o ios::app.


Não use ios_base::app. Simplesmente abra o arquivo e grave o novo conteúdo de cabeçalho no início do arquivo (use arquivo.seekp(0), se necessário). Depois disso, vá para o final do arquivo (arquivo.seekp(0, ios_base::end)) e grave o conteúdo.

Se for um arquivo novo, nenhum dos dois seekp()s será necessário. Se não houver conteúdo anterior a ser preservado, também não, e você poderá colocar a opção ios_base::trunc na hora de abrir o arquivo ou inicializar o objeto.


7. Arquivo binário em c++ com cabecalho

Bruno
uNclear

(usa Slackware)

Enviado em 16/11/2016 - 13:08h

Se eu utilizar o seekp(0) para gravar o cabeçalho ele vai ficar sempre sobreescrevendo, que seria o correto. Mas seu eu colocar seekp(0, ios::end) para inserir o objeto, ele sempre vai ficar sobreescrevendo no fim do arquivo, precisaria de que cada inserçao de um objeto o ponteiro do arquivo andasse.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts