Ver Mensaje Individual
  #1 (permalink)  
Antiguo 07/07/2016, 12:40
aguml
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
¿Se puede optimizar el siguiente codigo?

Hola amigos, he estado liado con el tema de verificar archivos por lotes usando un hash. El problema surgio cuando la aplicacion que probé me creaba un archivo con todos los md5 en un orden para un directorio y luego me creaba otro archivo con todos los md5 en otro orden para una copia del mismo directorio. No se porque hacia eso y no me los muestra todos ordenados pero me puse a crearme una solucion rapida en C que lo que hace es abrir el primer archivo y va buscando cada md5 en el segundo y los va poniendo en un tercer archivo en el mismo orden.
Ciertamente cada linea tiene el hash y al lado la ruta relativa al archivo con lo que lo que busco para ordenar es la ruta y no el md5 ya que este puede haber cambiado y no lo encontraria.
El caso es que aparentemente parece que funciona pero tarda para unas 70000 lineas como 5 minutos para ordenarlas en un tercer archivo. ¿Hay alguna manera de optimizarlo sin usar bases de datos?
Aqui el codigo:
Código C:
Ver original
  1. //---------------------------------------------------------------------------
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <errno.h>
  7. #include <limits.h>
  8. #define SIZEMAX 1024
  9. //---------------------------------------------------------------------------
  10.  
  11. typedef enum {
  12.     STR2INT_SUCCESS,
  13.     STR2INT_OVERFLOW,
  14.     STR2INT_UNDERFLOW,
  15.     STR2INT_INCONVERTIBLE
  16. } str2int_errno;
  17.  
  18. int CheckFileError(FILE *fichero,char *fullpath)
  19. {
  20.     int error=0;
  21.  
  22.     if(fichero == NULL){
  23.         printf("No se pudo abrir el archivo %s. Asegurese de que la ruta y el nombre son correctos.\n",fullpath);
  24.         error=-1;
  25.     }
  26.     return error;
  27. }
  28. //---------------------------------------------------------------------------
  29.  
  30. void CerrarArchivos(FILE **origen1,FILE **origen2,FILE **destino2)
  31. {
  32.     if(*origen1 != NULL){
  33.         fclose(*origen1);
  34.         *origen1=NULL;
  35.         if(*origen2 != NULL){
  36.             fclose(*origen2);
  37.             *origen2=NULL;
  38.             if(*destino2 != NULL){
  39.                 fclose(*destino2);
  40.                 *destino2=NULL;
  41.             }
  42.         }
  43.     }
  44. }
  45. //---------------------------------------------------------------------------
  46.  
  47. int AbrirArchivos(FILE **origen1,FILE **origen2,FILE **destino2,char *pathOrigen1,char *pathOrigen2,char *pathDestino2)
  48. {
  49.     int error;
  50.  
  51.     *origen1=fopen(pathOrigen1,"r");
  52.     if((error=CheckFileError(*origen1,pathOrigen1))!=0){
  53.         CerrarArchivos(origen1,origen2,destino2);
  54.         system("pause");
  55.         return error;
  56.     }
  57.  
  58.     *origen2=fopen(pathOrigen2,"r");
  59.     if((error=CheckFileError(*origen2,pathOrigen2))!=0){
  60.         CerrarArchivos(origen1,origen2,destino2);
  61.         system("pause");
  62.         return error;
  63.     }
  64.  
  65.     *destino2=fopen(pathDestino2,"w");
  66.     if((error=CheckFileError(*destino2,pathDestino2))!=0){
  67.         CerrarArchivos(origen1,origen2,destino2);
  68.         system("pause");
  69.         return error;
  70.     }
  71.     return error;
  72. }
  73. //---------------------------------------------------------------------------
  74.  
  75. void clean(void)
  76. {
  77.     char a;
  78.     while(getchar()!='\n');
  79. }
  80. //---------------------------------------------------------------------------
  81.  
  82. void ObtenerRutas(char *pathOrigen1,char *pathOrigen2,char *pathDestino2,int *largoHash)
  83. {
  84.     int largo;
  85.  
  86.     printf("Introduce la ruta completa hacia el primer archivo:\n\t");
  87.     fgets(pathOrigen1,SIZEMAX,stdin);
  88.     largo=strlen(pathOrigen1);
  89.     if(pathOrigen1[largo-1]!='\n'){
  90.         clean();
  91.         printf("Ruta demasiado larga.\n");
  92.     }else{
  93.         pathOrigen1[largo-1]='\0';
  94.     }
  95.     printf("Introduce la ruta completa hacia el segundo archivo:\n\t");
  96.     fgets(pathOrigen2,SIZEMAX,stdin);
  97.     largo=strlen(pathOrigen2);
  98.     if(pathOrigen2[largo-1]!='\n'){
  99.         clean();
  100.         printf("Ruta demasiado larga.\n");
  101.     }else{
  102.         pathOrigen2[largo-1]='\0';
  103.     }
  104.     printf("Introduce la ruta completa para el archivo de salida:\n\t");
  105.     fgets(pathDestino2,SIZEMAX,stdin);
  106.     largo=strlen(pathDestino2);
  107.     if(pathDestino2[largo-1]!='\n'){
  108.         clean();
  109.         printf("Ruta demasiado larga.\n");
  110.     }else{
  111.         pathDestino2[largo-1]='\0';
  112.     }
  113.     printf("Introduce el numero de caracteres del hash: ");
  114.     scanf("%d",largoHash);
  115. }
  116. //---------------------------------------------------------------------------
  117.  
  118. //Para convertir el parametro del largo del hash de cadena a entero
  119. str2int_errno str2int(int *out, char *s, int base) {
  120.     char *end;
  121.     long l;
  122.    
  123.     if (s[0] == '\0' || isspace((unsigned char) s[0]))
  124.         return STR2INT_INCONVERTIBLE;
  125.     errno = 0;
  126.     l = strtol(s, &end, base);
  127.  
  128.     if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
  129.         return STR2INT_OVERFLOW;
  130.     if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN))
  131.         return STR2INT_UNDERFLOW;
  132.     if (*end != '\0')
  133.         return STR2INT_INCONVERTIBLE;
  134.     *out = l;
  135.     return STR2INT_SUCCESS;
  136. }
  137. //---------------------------------------------------------------------------
  138.  
  139. int CheckParams(int nParametros, char *parametros[], char *pathOrigen1,char *pathOrigen2,char *pathDestino2,int *largoHash)
  140. {
  141.     str2int_errno error_param_hash;
  142.     char mensaje[SIZEMAX];
  143.    
  144.     if(nParametros == 5){
  145.         strcpy(pathOrigen1,parametros[1]);
  146.         strcpy(pathOrigen2,parametros[2]);
  147.         strcpy(pathDestino2,parametros[3]);
  148.         error_param_hash=str2int(largoHash,parametros[4],10);
  149.         switch(error_param_hash){
  150.             case STR2INT_OVERFLOW:
  151.                 strcpy(mensaje,"STR2INT_OVERFLOW");
  152.             break;
  153.  
  154.             case STR2INT_UNDERFLOW:
  155.                 strcpy(mensaje,"STR2INT_UNDERFLOW");
  156.             break;
  157.  
  158.             case STR2INT_INCONVERTIBLE:
  159.                 strcpy(mensaje,"STR2INT_INCONVERTIBLE");
  160.             break;
  161.         }
  162.         if(error_param_hash != STR2INT_SUCCESS){
  163.             printf("Error en el parametro para el largo del hash. Error: %s\n",mensaje);
  164.             system("pause");
  165.             return -1;
  166.         }
  167.         if(*largoHash < 0){
  168.             printf("El valor asignado al largo del hash no puede ser menor que '0'.\nSi no hay hash ponga '0'.\n");
  169.             system("pause");
  170.             return -1;
  171.         }
  172.     }else if(nParametros > 1){
  173.         printf("parametros incorrectos.\n");
  174.         system("pause");
  175.         return -1;
  176.     }else{
  177.         ObtenerRutas(pathOrigen1,pathOrigen2,pathDestino2,largoHash);
  178.     }
  179.     return 0;
  180. }
  181. //---------------------------------------------------------------------------
  182.  
  183. void CrearFicheroOrdenado(char *pathOrigen1,char *pathOrigen2,char *pathDestino2,int largoHash)
  184. {
  185.     char buffer1[SIZEMAX];
  186.     char buffer2[SIZEMAX];
  187.     FILE *origen1=NULL,*origen2=NULL,*destino2=NULL;
  188.     int encontrado,largo,noEncontrados=0;
  189.  
  190.     if(AbrirArchivos(&origen1,&origen2,&destino2,pathOrigen1,pathOrigen2,pathDestino2)==0){
  191.         printf("Ha comenzado el proceso. No cierre esta ventana hasta que termine el proceso.");
  192.         while(!feof(origen1) && fgets(buffer1,sizeof(buffer1),origen1) != NULL){
  193.             encontrado=0;
  194.             rewind(origen2);
  195.             while(!feof(origen2) && fgets(buffer2,sizeof(buffer2),origen2) != NULL && encontrado == 0){
  196.                 largo=strlen(&buffer1[largoHash]);
  197.                 if(strncmp(&buffer1[largoHash],&buffer2[largoHash],largo)==0){
  198.                     encontrado=1;
  199.                     break;
  200.                 }
  201.             }
  202.             if(encontrado==1)
  203.                 fputs(buffer2,destino2);
  204.             else{
  205.                 fputs("\n",destino2);
  206.                 noEncontrados++;
  207.             }
  208.         }
  209.         CerrarArchivos(&origen1,&origen2,&destino2);
  210.         printf("Proceso finalizado.\n");
  211.         if(noEncontrados > 0)
  212.             printf("No se encontraron en \"%s\" %d entradas.\n",origen2,noEncontrados);
  213.         system("pause");
  214.     }
  215. }
  216. //---------------------------------------------------------------------------
  217.  
  218. //Se puede usar con parametros tambien
  219. int main(int argc, char* argv[])
  220. {
  221.     char pathOrigen1[SIZEMAX];
  222.     char pathOrigen2[SIZEMAX];
  223.     char pathDestino2[SIZEMAX];
  224.     int largoHash;
  225.  
  226.     if(CheckParams(argc,argv,pathOrigen1,pathOrigen2,pathDestino2,&largoHash) == 0)
  227.         CrearFicheroOrdenado(pathOrigen1,pathOrigen2,pathDestino2,largoHash);
  228.     return 0;
  229. }
  230. //---------------------------------------------------------------------------
El caso es que si está mas o menos ordenado al empezar pues cuanto mas avance mas tardará en encontrar el siguiente y asi hasta el final y si es muy largo el archivo pues se puede hacer eterno jajaja.