Dúvida para gravar em arquivo em C! [RESOLVIDO]

1. Dúvida para gravar em arquivo em C! [RESOLVIDO]

Nick Us
Nick-us

(usa Slackware)

Enviado em 07/05/2020 - 11:07h

Fiquei neste momento sem saber o que vou fazer para gravar um arquivo!
Possuo um arquivo com 7 linhas, cada linha 1 número, tipo: 1,2,3,4,5,6,7 OK.
Eu gostaria de Mudar apenas o número 2 deste arquivo, ou seja, eu quero alterar o texto da Linha 2, colocando outro texto no lugar!

É aqui que começa a minha dúvida: Eu pensei que eu poderia usar o fseek para isso, mas olhando o que ele faz, vi que não seria o caso, pois ele não faz uma Busca por número da linha, ele parece ter sido feito para trabalhar com o fwrite que grava Blocos inteiros, e não é assim que meu arquivo é. Trata-se apenas de um arquivo comum txt.

Eu sei que eu poderia varrer linha a linha do arquivo para encontrar a linha 2, mas nem faço idéia do que eu posso usar para modificar essa linha encontrada!

E a única forma que eu sei fazer é re-criar o arquivo com a linha 2 modificada, tipo copiar linha a linha, intervindo na linha que modificarei.
Porém achei meio feio fazer isso, se existir uma forma mais bonita de se fazer.

Será que existe alguma forma, alguma função, algo que eu possa apenas ler o arquivo original, ir para a linha 2 e gravar o que desejo na linha 2? Salvando esse mesmo arquivo? Quero fazer isso em C.


  


2. MELHOR RESPOSTA

Mauricio Ferrari
maurixnovatrento

(usa Slackware)

Enviado em 08/05/2020 - 12:41h


Sugiro fazer pelo método que você sabe, não consegui achar nada descente na internet pra ti.

___________________________________
Conhecimento não se Leva para o Túmulo.

3. Re: Dúvida para gravar em arquivo em C!

berghetti
berghetti

(usa Debian)

Enviado em 11/05/2020 - 22:34h

Sei que sua pergunta é "como ir para linha x deu um arquivo, sem usar loop",
situação que penso não ser possível, que mesmo que houvesse alguma função da biblioteca padrão para isso, não teria como ela faze-lo sem varrer o arquivo,
pois de que outra forma se pode determinar quando começa uma linha?

mas como nunca tinha "brincado com arquivos", quando li sua pergunta me bateu a curiosidade e fui tentar fazer alguma coisa.
basicamente o programa faz oque você quer (mas como você não quer).

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFF_STDIN 1024

int
main ( int argc, const char **argv )
{
if ( argc < 2 )
{
fprintf ( stderr,
"Usage %s <file> <line | default 1> <\"new string\" | stdin>\n"
"Ex: %s file.c < licence\n",
*argv,
*argv );
return EXIT_FAILURE;
}

const char *file = *++argv;

// linha a ser modificada, 1 é o padrão
const int mod_linha =
( *++argv ) ? isdigit ( **argv ) ? atoi ( *argv++ ) : 1 : 1;

char *new_value; // conteudo novo a ser inserido
size_t new_value_l; // tamanho do novo conteudo

// pega novo valor por argumento
if ( *argv )
{
new_value = ( char * ) *argv;
new_value_l = strlen ( new_value );
}
// pega novo valor da entrada padrão
else
{
size_t len_buffer = BUFF_STDIN;
char *temp = calloc ( 1, len_buffer );
if ( !temp )
{
perror ( "Falha alocação de memoria" );
return EXIT_FAILURE;
}

char *line = NULL;
size_t line_l = 0;
size_t bytes_read = 0;
size_t bytes_read_tmp;

while ( ( bytes_read_tmp = getline ( &line, &line_l, stdin ) ) != -1 )
{
if ( bytes_read + bytes_read_tmp >= len_buffer )
{
len_buffer = ( bytes_read + bytes_read_tmp ) * 2;
if ( !( temp = realloc ( temp, len_buffer ) ) )
{
perror ( "Falha alocação de memoria" );
return EXIT_FAILURE;
}
}

memcpy ( temp + bytes_read, line, bytes_read_tmp );
bytes_read += bytes_read_tmp;
}

free ( line );
new_value = temp;
new_value_l = bytes_read;
}

// coloca quebra de linha caso não tenha
if ( new_value[new_value_l - 1] != '\n' )
{
new_value[new_value_l] = '\n';
new_value_l++;
}

// abre o arquivo para leitura
FILE *file_r = fopen ( file, "rb" );
if ( !file_r )
{
perror ( "falha abrir arquivo" );
return EXIT_FAILURE;
}

// vai para final do arquivo e pega quantos bytes arquivo possui
fseek ( file_r, 0L, SEEK_END );
long len_file_r = ftell ( file_r );

char *buffer = calloc ( 1, len_file_r + new_value_l );

// retornar para inicio do arquivo
// e le os dados para o buffer
rewind ( file_r );
if ( ( fread ( buffer, 1, len_file_r, file_r ) ) < len_file_r )
{
perror ( "falha ao ler arquivo" );
free ( buffer );
fclose ( file_r );
return EXIT_FAILURE;
}

fclose ( file_r );

// pega quantidade de bytes até começar linha a ser modificada
size_t pos_line;
int skip_line = mod_linha - 1;
for ( pos_line = 0; pos_line < len_file_r && skip_line; pos_line++ )
{
if ( buffer[pos_line] == '\n' )
skip_line--;
}

if ( skip_line )
{
fprintf ( stderr,
"arquivo possui apenas %d linha(s)\n",
mod_linha - skip_line - 1 );
if ( *argv )
free ( new_value );
free ( buffer );
fclose ( file_r );
return EXIT_FAILURE;
}

// pega o tamanho da linha atual a ser modificada
size_t len_cur_line = 0;
while ( buffer[pos_line + len_cur_line++] != '\n' )
;

// novo tamanho que o arquivo editado terá
size_t write_len;
if ( new_value_l == len_cur_line )
{
// copia os novos bytes por cima
for ( size_t i = 0; i < new_value_l; i++ )
buffer[i + pos_line] = new_value[i];

write_len = len_file_r;
}
else if ( new_value_l > len_cur_line )
{
// desloca os dados para direita para "abrir espaço" para novo dado
for ( size_t i = len_file_r; i > pos_line + len_cur_line - 1; i-- )
buffer[i + ( new_value_l - len_cur_line )] = buffer[i];

// copia os novos bytes
for ( size_t i = 0; i < new_value_l; i++ )
buffer[i + pos_line] = new_value[i];

write_len = len_file_r + ( new_value_l - len_cur_line );
}
else if ( new_value_l < len_cur_line )
{
// desloca os dados para esquerda
for ( size_t i = pos_line + len_cur_line; i < len_file_r; i++ )
buffer[i - ( len_cur_line - new_value_l )] = buffer[i];

// copia os novos bytes
for ( size_t i = 0; i < new_value_l; i++ )
buffer[i + pos_line] = new_value[i];

write_len = len_file_r - ( len_cur_line - new_value_l );
}

// abre para escrita
FILE *file_w = fopen ( file, "wb" );
if ( !file_w )
{
perror ( "falha abrir arquivo" );
free ( buffer );
return EXIT_FAILURE;
}

if ( ( fwrite ( buffer, 1, write_len, file_w ) ) < write_len )
{
perror ( "falha ao salvar arquivo" );
if ( !*argv )
free ( new_value );

free ( buffer );
fclose ( file_w );
return EXIT_FAILURE;
}

if ( !*argv )
free ( new_value );

free ( buffer );
fclose ( file_w );

return EXIT_SUCCESS;
}




4. Re: Dúvida para gravar em arquivo em C!

Nick Us
Nick-us

(usa Slackware)

Enviado em 12/05/2020 - 12:47h

berghetti escreveu:Sei que sua pergunta é "como ir para linha x deu um arquivo, sem usar loop",
situação que penso não ser possível, que mesmo que houvesse alguma função da biblioteca padrão para isso, não teria como ela faze-lo sem varrer o arquivo,
pois de que outra forma se pode determinar quando começa uma linha?

mas como nunca tinha "brincado com arquivos", quando li sua pergunta me bateu a curiosidade e fui tentar fazer alguma coisa.
basicamente o programa faz oque você quer (mas como você não quer).
[/code]

Tipo dá pra fazer isso com menos de 5 a 10 linhas digitadas
1) Use um for para varrer linha a linha e abaixo dele grave a linha para um novo arquivo
2) um IF para verificar se está na linha correta apenas isso, e se estiver grave nesta linha o que deseja modificar
3) renomeie o arq temp para seu arquivo original

Quando fiz a pergunta é porque eu queria isso de uma forma bonita, mas acabei por descobrir que não existe mesmo isso em C através de outra pergunta parecida que fiz

De qualquer forma seu código vai ajudar muitas outras pessoas! Pois vc implementa muita coisa interessante que as pessoas gostam de estudar, até mesmo eu! Então ter exemplos de como cada um faz, ou métodos diferentes de como se faz ajuda muita gente!







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts