Ir ao conteúdo
  • Cadastre-se
Vitor Avancini

Posição do ponteiro em arquivos c++

Recommended Posts

Essas linhas deveriam ser responsável por colocar o ponteiro na decima posição do meu arquivo e assim escrever o conteúdo de "lenght" que é um short no arquivo e depois escrever o conteúdo de "buffer" no arquivo.  

	arq.seekp(9, ios::end);//reserva os 10 primeiros bytes para o cabeçalho
	//cout << arq.tellp() << endl;
	//cout << buffer << endl;
	//campo flag de excluido (avail list)
	arq.write((char*)&length, sizeof(length));
	arq.write(buffer, length);
	//cout << arq.tellp() << endl;

Porém ele escreve na primeira posição, simplesmente ignorando o seekp... Há algo de errado ai?

Compartilhar este post


Link para o post
Compartilhar em outros sites

nãos custa, achei que fosse desnecessário, vou colocar o código de função de leitura e escrita

ESCRITA:

void EstagioAluno::writeEA (ofstream &arq)
{
	char buffer [1000];
	char aux [20];
	short length;
	itoa(matricula, buffer, 10);
	strcat(buffer, "|");
	strcat(buffer, nomeCompleto);
	strcat(buffer, "|");
	strcat(buffer, tipoEstagio);
	strcat(buffer, "|");
	strcat(buffer, nomeEmpresa);
	strcat(buffer, "|");
	strcat(buffer, cnpj);
	strcat(buffer, "|");
	strcat(buffer, nomeSupervisor);
	strcat(buffer, "|");
	strcat(buffer, dataInicio);
	strcat(buffer, "|");
	strcat(buffer, dataFim);
	strcat(buffer, "|");
	strcat(buffer, dataEntregaRelatorioParcial);
	strcat(buffer, "|");
	strcat(buffer, situacao);
	strcat(buffer, "|");
	itoa(horasPrevistas, aux, 10);//converte int em char na base 10 e passa para aux
	strcat(buffer, aux);
	strcat(buffer, "|");
	itoa(horasTotalizadas, aux, 10);//converte int em char na base 10 e passa para aux
	strcat(buffer, aux);
	strcat(buffer, "|");
	strcat(buffer, parecerFinal);
	strcat(buffer, "|");
	length = (short) strlen(buffer);		
	arq.seekp(9, ios::end);//reserva os 10 primeiros bytes para o cabeçalho
	cout << arq.tellp() << endl;
	cout << buffer << endl;
	//campo flag de excluido (avail list)
	arq.write((char*)&length, sizeof(length));
	arq.write(buffer, length);
	cout << arq.tellp() << endl;
}

LEITURA:

void EstagioAluno::readEA(ifstream &arq)
{
	short lenght;
	char *buffer;
	arq.seekg(9);//aponta para o décimo bytes
	
	while(!arq.eof())
	{
		arq.read((char*)&lenght, sizeof(lenght));
		buffer = new char[lenght];
		buffer[lenght] = '\0';
		arq.read(buffer, lenght);
		cout << buffer << endl;
	}
}

Consegue me ajudar?

Compartilhar este post


Link para o post
Compartilhar em outros sites

MAIN:

#include <string>
#include <cstring>
#include <cstdlib>
#include <ostream>
#include <fstream>
#include <iostream>
#include "Estagio.h"

using namespace std;

int main ()
{
	EstagioAluno ea;
	ofstream arq1;
	ifstream arq2;
	int op = 0;
	
	do{
		 printf("\n___________________________\n");
        printf("          ESTAGIOS         |\n");
        printf("___________________________|\n");
		printf("1 - Adicionar Estagio\t   |");	
		printf("\n2 - Ler arquivo\t\t   |");
		printf("\n0 - Sair\t\t   |");
		printf("\n___________________________|\n");
		printf("\nDigite a opcao: ");
		setbuf(stdin, NULL);
		scanf("%d", &op);
		switch(op)
		{
			case 0:
				printf("Fechando sistema!");
				break;
			case 1:
				arq1.open ("estagios.txt", ios::binary|ios::app);	
				if (!arq1.good())
				{
					cerr<< "Não foi possível abrir o arquivo."<<endl;
					exit(1);
					
				}
				ea.PreencherEA();
				ea.writeEA(arq1);
				arq1.close();
				break;
			case 2:
				arq2.open("estagios.txt", ios::binary);
				if (!arq2.good())
				{
					cerr<< "Nao foi possivel abrir o arquivo."<<endl;
					exit(2);
				}
				ea.readEA(arq2);
				arq2.close();
				break;
			default:
				printf("Opcao invalida.");
				break;
		}
	}while (op != 0);	
}

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

O problema não está na abertura. Certamente está na forma de tratar o arquivo.
Não entendo coisas como: arq.seekp(9, ios::end);//reserva os 10 primeiros bytes para o cabeçalho

seekp não reserva nada, supondo que em um arquivo a primeira linha comece com
"Alo mundo!XXXXXXXXXXXXX...."

com arq.seekp(9, ios::end); você se posiciona em 'o' ou '!', não sei muito bem, na realidade você não está reservando nada aí, não entendo a lógica.

 

porém esse não é o único problema acho.... fica difícil deduzir os erros por que não posso realizar provas, tenho umas mil teorias de onde pode estar o problema e pode que nenhuma seja certa pois só vejo fragmentos de código.

 

A ver.... vamos deixar pra lá. Ou você me passa o enunciado ou me passa os fontes, com fragmentos fica difícil, não sei que dados você está enviando ao arquivo, nem como os estas tomando por teclado.

 

O único que preciso saber é qual são os dados que você envia ao arquivo? Que aspecto tem o arquivo, tem um cabeçalho, e depois quê? um string? uma estrutura? Faça um esboço do arquivo com ao menos 2 ou 3 dados que envia ao file. tipo

arquivo cobrança | pedro cuco | 28 | etc | outro pedro | 69 | outro etc |.....

sendo
arquivo cobrança |  //<- cabeçalho

pedro cuco | 28 | etc | //<-dados1

outro pedro | 69 | outro etc |//<-dados2

...

 

Isso é para ter uma ideia.

 

Se não acho que não da não.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

O problema é o seguinte, eu preciso de reservar as 10 primeiras posições do arquivo para usar posteriormente como o cabeçalho do arquivo, então gostaria de pular as 10 primeiras posições e escrever a partir da décima, agora deu pra entender?

Os dados ficariam dessa forma:

1ª inserção:

{  1328413|vitor avancini cabral|curricular|qualquer|123456|thiago|13/02/2016|14/07/2016|20/07/2016|concluido|200|200|tudo

2ª inserção

x 123|seila silva souza|em andamento|casa da mae joana|123456|thiago

|12/12/12|20/03/13|25/03/13|concluido|100|110|sucesso|ok| 

 

sendo que a "{" deverá ficar na décima posição. A "{" na verdade é um short que indica o tamanho do meu registro  

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu tenho essa estrutura:

class EstagioAluno
{
	private:
	int matricula;
	char nomeCompleto [50];
	char tipoEstagio[13];
	char nomeEmpresa[20];
	char cnpj[20];
	char nomeSupervisor[50];
	char dataInicio[11];
	char dataFim[11];
	char dataEntregaRelatorioParcial[11];
	char situacao[11];
	int horasPrevistas;
	int horasTotalizadas;
	char parecerFinal[401];
  public:
  //declaração dos métodos
};

e preencho ela desta forma:

void EstagioAluno::PreencherEA()
{
	cout << "Matricula: "; cin >> matricula;
	cout << "Nome Completo: "; cin.ignore(); cin.getline(nomeCompleto, 50); 
	cout << "Tipo de Estagio: "; /*cin.ignore();*/ cin.getline(tipoEstagio, 13);
	cout << "Nome da Empresa: "; /*cin.ignore();*/ cin.getline(nomeEmpresa, 20);
	cout << "CNPJ: "; /*cin.ignore();*/ cin.getline(cnpj, 20);
	cout << "Nome do supervisor do estagio: "; /*cin.ignore();*/ cin.getline(nomeSupervisor, 50);
	cout << "Data de inicio: "; /*cin.ignore();*/ cin.getline(dataInicio, 11);
	cout << "Data Final: "; /*cin.ignore();*/ cin.getline(dataFim, 11);
	cout << "Data de entrega do relatorio parcial: "; /*cin.ignore();*/ cin.getline(dataEntregaRelatorioParcial, 11);
	cout << "Situacao do estagio: "; /*cin.ignore();*/ cin.getline(situacao, 11);
	cout << "Quantidade de horas previstas: "; /*cin.ignore();*/ cin >> horasPrevistas;
	cout << "Quantidade de horas totalizadas: "; /*cin.ignore();*/ cin >> horasTotalizadas;
	cout << "Parecer final do coordenador de estagio: "; cin.ignore(); cin.getline(parecerFinal, 401);
}

primeiro passo para o arquivo uma variável short que indica o tamanho do registro (registro é o conjunto de atributos que pertencem a um mesmo objeto) e logo após junto em um buffer todos os atributos com "|" separando cada campo, desta forma:

void EstagioAluno::writeEA (ofstream &arq)
{
	char buffer [1000];
	char aux [20];
	short length;
	itoa(matricula, buffer, 10);
	strcat(buffer, "|");
	strcat(buffer, nomeCompleto);
	strcat(buffer, "|");
	strcat(buffer, tipoEstagio);
	strcat(buffer, "|");
	strcat(buffer, nomeEmpresa);
	strcat(buffer, "|");
	strcat(buffer, cnpj);
	strcat(buffer, "|");
	strcat(buffer, nomeSupervisor);
	strcat(buffer, "|");
	strcat(buffer, dataInicio);
	strcat(buffer, "|");
	strcat(buffer, dataFim);
	strcat(buffer, "|");
	strcat(buffer, dataEntregaRelatorioParcial);
	strcat(buffer, "|");
	strcat(buffer, situacao);
	strcat(buffer, "|");
	itoa(horasPrevistas, aux, 10);//converte int em char na base 10 e passa para aux
	strcat(buffer, aux);
	strcat(buffer, "|");
	itoa(horasTotalizadas, aux, 10);//converte int em char na base 10 e passa para aux
	strcat(buffer, aux);
	strcat(buffer, "|");
	strcat(buffer, parecerFinal);
	strcat(buffer, "|");
	length = (short) strlen(buffer);		
	arq.seekp(9, ios::end);//reserva os 10 primeiros bytes para o cabeçalho
	cout << arq.tellp() << endl;
	cout << buffer << endl;
	//campo flag de excluido (avail list)
	arq.write((char*)&length, sizeof(length));
	arq.write(buffer, length);
	cout << arq.tellp() << endl;
}

Gostaria de escrever o primeiro registro na decima posição do arquivo e não na primeira, por isso o seekp. Porém no atual momento a escrita ocorre na primeira posição

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Vitor,

 

A linha de código

arq.seekp(9, ios::end);

pula para a décima posição a partir do fim, não do início. Tenta assim:

arq.seekp(9, ios::beg);

A linha de código acima pula para a décima posição a partir do início do arquivo.

Compartilhar este post


Link para o post
Compartilhar em outros sites
17 horas atrás, danieltm64 disse:

Olá Vitor,

 

A linha de código


arq.seekp(9, ios::end);

pula para a décima posição a partir do fim, não do início. Tenta assim:


arq.seekp(9, ios::beg);

A linha de código acima pula para a décima posição a partir do início do arquivo.

Boa tarde @danieltm64 , fiz essa modificação, porém não ocorre o esperado e a escrita ocorre a partir da primeira posição.

desde já agradeço

Compartilhar este post


Link para o post
Compartilhar em outros sites

Opa! Esqueci de responder o post! HAHAH Sinto muito.
Talvez o problema seja que você esta abrindo o arquivo desta forma: arq1.open ("estagios.txt", ios::binary|ios::app);

 

ios::app é o problema certamente, pois esse "flag" só permite você adicionar conteúdo, em outras palavras você sempre vai inserir o conteúdo ao final do arquivo =)


prove isso e diga se resolveu

Compartilhar este post


Link para o post
Compartilhar em outros sites

Depois de muito indagar no assunto e consultar com outros programadores cheguei a conclusão de que seu modo de abertura está completamente errado. você usa o modo: arq1.open ("estagios.txt", ios::binary|ios::app); e para poder alterar um arquivo binário você precisa dos flags std::fstream::in | std::fstream::out | std::fstream::binary. Ao não ter o flag in o conteúdo se borra pois ofstream tem por default o efeito trunc caso não adicione o flag in. É compreensível... se nós adicionamos o flag in quer dizer que queremos ler. Mas como vamos ler se o conteúdo do arquivo é destruído? Pois ao adicionar o flag in isso não acontece.

 

A coisa vai da seguinte forma...
Mediante uma combinação de flags você tem efeitos semelhantes da mesma forma que o linguagem C, porém a coisa é algo mais confusa na linguagem C++, ou pelo menos acho assim. Aqui nessa pagina que anexo ao final você tem a tabela de equivalência na qual você pode consultar os flags que deve por em cada tipo de operação sobre os arquivos tanto em C como em C++, recomendo guardar essa pagina.
http://en.cppreference.com/w/cpp/io/basic_filebuf/open

 

Com esses flags std::fstream::in | std::fstream::out | std::fstream::binary você poderá editar seu arquivo tranquilamente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O que eu me pergunto é: por que o seekp não funciona?

arq.seekp(9, ios::beg)

isso deveria ser responsável por mexer com os ponteiros do arquivo, ou estou errado?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vou lhe deixar um exemplo:

#include <iostream>
#include <fstream>
using namespace std;

class EstagioAluno
{
	private:
	int matricula;
	char nomeCompleto [50];
	char tipoEstagio[13];
	char nomeEmpresa[20];
	char cnpj[20];
	char nomeSupervisor[50];
	char dataInicio[11];
	char dataFim[11];
	char dataEntregaRelatorioParcial[11];
	char situacao[11];
	int horasPrevistas;
	int horasTotalizadas;
	char parecerFinal[401];
  public:
  //declaração dos métodos
};

int main (){
    //vamos supor que você tem um int e um string resultante em cada bloco de dados que quer enviar ao arquivo, converter a struct em char* é problema seu, mas recomendo você usar a classe string pois é bem melhor para se trabalhar.
    string vetor1 = "1328413|vitor avancini cabral|curricular|qualquer|123456|thiago|13/02/2016|14/07/2016|20/07/2016|concluido|200|200|tudo";
    unsigned int n1 = vetor1.length();
    
    string vetor2 = "123|seila silva souza|em andamento|casa da mae joana|123456|thiago|12/12/12|20/03/13|25/03/13|concluido|100|110|sucesso|ok";
    unsigned int n2 = vetor2.length();    

    //Abrimos o arquivo desta forma, porém o arquivo deve existir antes ou o programa vai dar erro pois com esses modos de abertura não será criado um arquivo, "esse modo só edita".
    ofstream out("prova.dat", std::fstream::in | std::fstream::out | std::fstream::binary | std::fstream::trunc ); // truncamos para que se escreva um novo arquivo, só para provas, tire o trunc se desejar
    //Se o arquivo não existe da erro e baybay!
    if(!out.is_open()){
        cout << "fail" << endl;
        return 1;
    }
    
    //Essa é a forma correta para inserir os dados no arquivo
    out.write(reinterpret_cast<const char*>( &n1 ) , sizeof (int));
    out.write(reinterpret_cast<const char*>( vetor1.c_str() ) , n1);   
    
    //vamos gravar 2 vezes mais, agora com o int que é length(vetor2) + vetor2
    out.write(reinterpret_cast<const char*>( &n2 ) , sizeof (int));
    out.write(reinterpret_cast<const char*>( vetor2.c_str() ) , n2);  //c_str() quer dizer string de c ou seja char* ^_^
    
    //repetimos mais uma vez os primeiros dados... é só para ter algo no arquivo e fazer provas
    out.write(reinterpret_cast<const char*>( &n1 ) , sizeof (int));
    out.write(reinterpret_cast<const char*>( vetor1.c_str() ) , n1);           
    
    //ok... temos 3 blocos com dados no arquivo, pode averiguar se quiser. Fechamos logo depois de editar, é importante par aque se salve as mudanças que fizemos.
    out.close();
    
    //Agora vamos ler o primeiro contato
    ifstream in("prova.dat", std::fstream::in | std::fstream::binary );

    if(!in.is_open()){
        cout << "fail" << endl;
        return 2;
    }
    
    unsigned int tamanhoFrase;
    string frase;
    //Paso1: Lemos o int que vai dizer quantos chars devemos ler para obter o primeiro contato
    in.read( reinterpret_cast<char*>( &tamanhoFrase ), sizeof (int)); 
    
    //Paso2: lemos o contato em base ao inteiro que foi lido anteriormente.
    char* temp = new char[tamanhoFrase+1]; //para ler precisamos de um autentico string de C ou ler letra por letra no nosso string(classe)
    in.read( temp, tamanhoFrase); //lemos a frase  
    temp[tamanhoFrase] = '\0'; //Ao ser um string do linguagem C é preciso por o NULL ao final da frase, por isso declaramos temp com new char[tamanhoFrase+1], esse +1 é para o NULL que indica onde termina a frase
    frase = temp;  // Nesse ponto você pode jogar temp de volta a um objeto do tipo string se lhe parecer bem, ou pode continuar com temp. aconselho trabalhar com strings de C++
    delete [] temp; //É importante sempre não esquecer liberar, reservou tem que liberar, é regra.
    
    
    cout << "Tamanho do bloco: " << tamanhoFrase << endl;
    cout << frase << endl;
    
    //para ler cada contato você deve fazer a mesma coisa que os 2 passo anteriores, e aconselho você 
    //ir usando tellg para ir anotando a posição inicial de cada dado que for ler, assim você pode 
    //voltar ao inicio desse bloco de dados caso seja o que você está buscando
    
    out.close();
    in.close();
    return 0;
}


Respondendo sua pergunta:
Se você tiver: um short mais o string "1328413|vitor avancini cabral|curricular|qualquer|123456|thiago|13/02/2016|14/07/2016|20/07/2016|concluido|200|200|tudo", você tem 2Bytes+120Bytes, se usar seekp para mover o fileptr 9 casinhas(bytes) você irá parar aqui justo->"|vitor avancini..." ja que 2bytes+"1328413", essa é a décima posição. Então acho que você ta confundindo a forma de trabalhar com arquivos binários, dai vem todo seu problema vei.

 

tenha claro que
int n = 123;
e
char v[] ="123";

não são a mesma coisa. if( n == v ) FALSO! write envia n(int) ao arquivo e não v(string). você deveria ler 4 bytes com a função read e alojar esses dados em um int. Dai que eu não to entendendo sua lógica ao dizer que seekp avança 9...




 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então, @vangodp, o meu problema determina que eu comece a escrever no arquivo a partir da décima posição, ou seja, não posso utilizar as 10 primeiras posição. Caso você esteja curioso para saber o porque devo não utilizar as 10 primeiras posições a resposta é que nesse local não utilizado eu irei preencher com outras informações, por exemplo o tamanho total do arquivo, o "endereço" para um registro excluído etc. 

Bom, acredito que deu pra entender o que quis dizer. Há alguma forma de escrever no arquivo pulando as 10 primeiras posições?  

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×