Ir ao conteúdo
  • Cadastre-se

C Uma maneira nada convencional de copiar arquivos.


KXSY

Posts recomendados

Estou deixando o meu dever de casa pra quem quiser dá uma olha, basicamente e uma maneira de copiar arquivos.

/* Copiando arquivos da maneira mais difícil */
#include <stdio.h>
#include <stdlib.h>

/* Constantes */

/* Tamanho do buffer */
#define TAM_BUFFER 512

/* Quantidade de caracteres do nome do arquivo */
#define T_N_ARQUIVO 64


int main(void)
{
   FILE *origem/*Arquivo de origem*/,*destino/* Arquivo de destino*/;
   unsigned long tam_arquivo;     /* Tamanho do arquivo em bytes */
   char n_arquivo[T_N_ARQUIVO];      /* Nome do arquivo */
   char *buffer;
   /* Abre o arquivo a ser copiado */
   printf("\nDigite o nome do arquivo para ser copiado:\t");
   scanf("%s",n_arquivo);
   origem=fopen(n_arquivo,"rb");
   if(!origem)
   {
      perror("\nArquivo não encontrado.\n");
      return(-1);
   }

   /* Pega o tamanho do arquivo */
   /* Maneira portavel */
   for(tam_arquivo=0; !feof(origem); tam_arquivo++)
      fread(&n_arquivo[0],sizeof(char),1,origem);
      /*fgetc(origem); Aqui seria totalmente aceitavel usar fgetc() */
   tam_arquivo-=1;
   rewind(origem);      /* Coloca o ponteiro do arquivo no começo */

   /* Não portavel */
   /*fseek(origem,0,SEEK_END);
   tam_arquivo=ftell(origem);
   fseek(origem,0,SEEK_SET);*/
   printf("\nArquivo aberto e pronto para ser copiado.\n");
   printf("\nTamanho em bytes:%lu",tam_arquivo);
   printf("\nDigite o nome do arquivo de destino:\t");
   scanf("%s",n_arquivo);
   destino=fopen(n_arquivo,"wb+");
   if(!destino)
   {
      printf("\nVerifique se você possui privilegios para acessar essa area.");
      perror("\nNão foi possivel criar o arquivo de destino.\n");
      fclose(origem);
      return(-1);
   }
   /* Reserva o buffer de copia */
   buffer=malloc(sizeof(char)*TAM_BUFFER);
   if(!buffer)
   {
      fclose(origem);
      fclose(destino);
      perror("\nNão foi possível reservar memoria no sistema!\n");
      return(-1);
   }
   do
   {
      if(tam_arquivo>TAM_BUFFER)
      {
         fread(buffer,sizeof(char),TAM_BUFFER,origem);
         fwrite(buffer,sizeof(char),TAM_BUFFER,destino);
         tam_arquivo-=TAM_BUFFER;
      }
      else
      {
         fread(buffer,sizeof(char),tam_arquivo,origem);
         fwrite(buffer,sizeof(char),tam_arquivo,destino);
         tam_arquivo=0;
      }
   }while(tam_arquivo);
   printf("\nArquivo copiado com sucesso.\n");
   /* Libera a memoria do buffer */
   free(buffer);
   fclose(origem);      /* Fecha o arquivo que foi copiado */
   fclose(destino);     /* Fecha o arquivo de destino da copia */
   return(0);
}

falta ainda verifica a copia do arquivo.

 

Atenção: não use esse código em maquinas com o windows 9x que provavelmente vai travar.

  • Curtir 2
  • Amei 1
Link para o comentário
Compartilhar em outros sites

2 horas atrás, isrnick disse:

Qual seria o convencional? Eu achava que esse é o método convencional...

Vejo muita gente usando sendfile por ser mais rápido ou open, write e read para ter uma compatibilidade com o windows e linux.

 

Agora em disparado o que eu mais veja é assim

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

/* Constantes */
#define T_NOME 20
#define T_ARG 100

int main()
{
  char n_origem[T_NOME],n_destino[T_NOME];
  char argumento[T_ARG];
  printf("\nDigite o nome do arquivo:\t");
  scanf("%s",n_origem);
  getchar();
  printf("\nDigite o nome do destino do arquivo:\t");
  scanf("%s",n_destino);
  getchar();
  #ifdef _WIN32
    sprintf(argumento,"copy %s %s",n_origem,n_destino);
  #else
    sprintf(argumento,"cp %s %s",n_origem,n_destino);
  #endif
  system(argumento);
  return(0);
}

no windows tem também a opção do copyfile.

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Usar system() é uma má ideia por muitos motivos, as pessoas aprendem a fazer assim por ser fácil, e pode até ser útil quando precisa de algo para uso próprio que possa ser feito rápido mas será descartado depois, mas não é uma solução viável para qualquer coisa mais que isso.

 

sendfile e copyfile realmente podem ser mais rápidos, mas não são portáveis, mas são boas opções se vai programar para seus respectivos SO, ou então se vai usar #ifdef _WIN32 #else #endif elas seriam melhores opções do que usar system().

 

open, read e write são funções POSIX e também são opções mais rápidas por não usarem buffer, e também podem ser boas opções, mas a Microsoft as considera funções descontinuadas substituindo-os por _open, _read e _write:

 

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/open?view=vs-2019

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-read?view=vs-2019

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-write?view=vs-2019

 

fopen, fread e fwrite apesar de não serem tão rápidas por usarem buffer, são funções da biblioteca padrão da linguagem C logo são a melhor opção para programar algo que provavelmente funcionará em qualquer situação.

 

Portanto considero que uma solução usando fopen, fread e fwrite seria a solução padrão, e as outras seriam opções extras que podem ser mais adequadas dependo da necessidade ou situação.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Versão final.

/* Copia arquivos */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

/* Tamanho do buffer */
#define TAM_BUFFER 512

/* Quantidade de caracteres do nome do arquivo */
#define T_N_ARQUIVO 64


int main(int q_argumentos, char *argumentos[])
{
   FILE *origem/*Arquivo de origem*/,*destino/* Arquivo de destino*/;
   unsigned long tam_arquivo;     /* Tamanho do arquivo em bytes */
   char n_arquivo[T_N_ARQUIVO];      /* Nome do arquivo */
   char *buffer1=NULL,*buffer2=NULL,tecla=0;
   unsigned long progresso,cont;
   /* Abre o arquivo a ser copiado */
   printf("\nDigite o nome do arquivo para ser copiado:\t");
   scanf("%s",n_arquivo);
   origem=fopen(n_arquivo,"rb");
   if(!origem)
   {
      perror("\nArquivo não encontrado.\n");
      return(-1);
   }

   /* Pega o tamanho do arquivo */
   /* Maneira portavel */
   for(tam_arquivo=0; !feof(origem); tam_arquivo++)
      fread(&n_arquivo[0],sizeof(char),1,origem);
      /*fgetc(origem); Aqui seria totalmente aceitavel usar fgetc() */
   tam_arquivo-=1;
   rewind(origem);      /* Coloca o ponteiro do arquivo no começo */

   /* Não portavel */
   /*fseek(origem,0,SEEK_END);
   tam_arquivo=ftell(origem);
   fseek(origem,0,SEEK_SET);*/
   printf("\nArquivo aberto e pronto para ser copiado.\n");
   printf("\nTamanho em bytes:%lu",tam_arquivo);
   printf("\nDigite o nome do arquivo de destino:\t");
   scanf("%s",n_arquivo);
   destino=fopen(n_arquivo,"wb+");
   if(!destino)
   {
      printf("\nVerifique se você possui privilegios para acessar essa area.");
      perror("\nNão foi possivel criar o arquivo de destino.\n");
      fclose(origem);
      return(-1);
   }
   /* Reserva o buffer de copia */
   buffer1=malloc(sizeof(char)*TAM_BUFFER);
   if(!buffer1)
   {
      perror("\nNão foi possível reservar memoria no sistema!\n");
      return(-1);
   }
   progresso=tam_arquivo;
   cont=1;
   do
   {
      if(tam_arquivo>TAM_BUFFER)
      {
         fread(buffer1,sizeof(char),TAM_BUFFER,origem);
         fwrite(buffer1,sizeof(char),TAM_BUFFER,destino);
         tam_arquivo-=TAM_BUFFER;
         cont+=TAM_BUFFER;
      }
      else
      {
         fread(buffer1,sizeof(char),tam_arquivo,origem);
         fwrite(buffer1,sizeof(char),tam_arquivo,destino);
         cont+=tam_arquivo;
         tam_arquivo=0;
      }
      printf("\nProgresso\n");
      printf("%.0f%%",(cont*1.0/progresso)*100);
   }while(tam_arquivo);
   tam_arquivo=progresso;
   printf("\nArquivo copiado com sucesso.\n");
   printf("\nTestar arquivo copiado S/N:\t");
   scanf("%c",&tecla);
   getchar();
   /* Compara os arquivos. */
   if(toupper(tecla)!='S')
   {
      fseek(origem,0,SEEK_SET);
      fseek(destino,0,SEEK_SET);
      buffer2=malloc(sizeof(char)*TAM_BUFFER);
      if(!buffer2)
      {
         perror("\nNão foi possível reservar memoria no sistema!\n");
         fclose(origem);
         fclose(destino);
         free(buffer1);
         /* Até parece, que quando der erro vai executar até aqui! */
         return(-1);
      }
      do
      {
         if(tam_arquivo>TAM_BUFFER)
         {
            fread(buffer1,sizeof(char),TAM_BUFFER,origem);
            fread(buffer2,sizeof(char),TAM_BUFFER,destino);
            if(memcmp(buffer1,buffer2,TAM_BUFFER))
            {
               printf("\nHá um erro no arquivo copiado.\n");
               printf("\n\nApagar arquivo copiado S/N:\t");
               scanf("%c",&tecla);
               getchar();
               if(toupper(tecla)=='S')
               {
                  fclose(destino);
                  destino=NULL;
                  remove(n_arquivo);
               }
               break;
            }
            tam_arquivo-=TAM_BUFFER;
         }else
         {
            fread(buffer1,sizeof(char),tam_arquivo,origem);
            fread(buffer2,sizeof(char),tam_arquivo,destino);
            if(memcmp(buffer1,buffer2,tam_arquivo))
            {
               printf("\nHá um erro no arquivo copiado.\n");
               printf("\n\nApagar arquivo copiado S/N:\t");
               scanf("%c",&tecla);
               getchar();
               if(toupper(tecla)=='S')
               {
                  fclose(destino);
                  destino=NULL;
                  remove(n_arquivo);
               }
               break;
            }
            tam_arquivo=0;
         }
      }while(tam_arquivo);
      printf("\nNão há erros no arquivo.\n");
   }
   /* Libera a memoria do buffer */
   free(buffer1);
   if(buffer2)
      free(buffer2);
   fclose(origem);      /* Fecha o arquivo que foi copiado */
   if(destino)
      fclose(destino);     /* Fecha o arquivo de destino da copia */
   return(0);
}

Só adicionei umas firulas novas, o resto e o mesmo código.

 

Provavelmente irei reescrever tudo de novo, porque me deparei com um erro que eu não consigo consertar quando vai pedir para checar o arquivo.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário 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 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...