Ir ao conteúdo
  • Cadastre-se

Posição do ponteiro em arquivos c++


Posts recomendados

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?

Link para o comentário
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?

Link para o comentário
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);	
}

 

Link para o comentário
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.

 

Link para o comentário
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  

Link para o comentário
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

Link para o comentário
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

Link para o comentário
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

Link para o comentário
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.

Link para o comentário
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...




 

Link para o comentário
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?  

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades 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

×
×
  • Criar novo...