Newsgroup: it.comp.lang.c
Titolo: velocizzare scrittura su file bufferizzando?

Ciao a tutti,
ho scritto questa funzioncina che salva su un file aperto in scrittura
e passato come input, l'allegato di una mail passata come "messaggio":
int writeAttach(FILE* f, char* messaggio) {
  const char* TOFIND = "filename=";
  char* res=strstr(messaggio, TOFIND);
  if (res != NULL) {
    // salta due linee vuote
    while (*res != 10 ) res++;
    while (*res != 10 ) res++;
    do {
      res++;
      putc(*res, f);
    } while (strstr(res, "------") != NULL);
  } else {
    return -1;
  }
  return 0;
}
Questa funzione non dà problemi se non di lentezza su file grandi, in
quanto come vedete elabora un carattere alla volta.
Sono convinto che si può scrivere più efficiente in termini di
prestazioni bufferizzando.
Qualche consiglio?
Grazie in anticipo.
G.

 Qualche consiglio?
Senza provare, ma il succo è questo.
int writeAttach(FILE* f, char* messaggio) {
  const char* TOFIND = "filename=";
  char* res=strstr(messaggio, TOFIND);
  char* buf=malloc(strlen(res)+1) ; // add
  int i = 0 ;  // add
  if (res != NULL) {
    // salta due linee vuote
    while (*res != 10 ) res++;
    while (*res != 10 ) res++;
    do {
      res++;
      buf[i++] = *res; // replace
    } while (strstr(res, "------") != NULL);
    buf[i] = 0; // add
    fputs(buf, f) ; // add
  } else {
    return -1;
  }
  free(buf);  // add
  return 0;
}

  } while (strstr(res, "------") != NULL);
Che cosa stai cercando di fare qui? Salvare carattere per carattere finché
non oltrepassi la sequenza "------"? Un modo bizzarro per farlo. Hai
trasformato in O(N^2) un'operazione che avrebbe complessità O(N).
Ad ogni modo, la tua funzione non fa quello che dici. O meglio: lo fa in
condizioni molto particolari. In generale, non funziona.
Max

trasformato in O(N^2) un'operazione che avrebbe complessità O(N).
Come l'avresti fatta?

}
Provata e funziona, cosě lavora in memoria ma č comunque molto lenta,
probabilmente il problema č che elabora un carattere alla volta e,
come dice Max, per ogni carattere testa strstr(res, "------").
Per allegati di 1MB esegue quel ciclo un milione di volte...
Altre idee?


wrote:

Tutto questo perché non conoscevo strcspn()...
alla fine ho fatto così:
int writeAttach(FILE* f, char* messaggio) {
  const char* TOFIND = "filename=";
  char* res=strstr(messaggio, TOFIND);
  if (res != NULL) {
    while (*res != 10 ) res++;
    while (*res != 10 ) res++;
    int toread = strcspn(res, "------");
    char* buf=malloc(toread+1);
    strncpy(buf, res, toread);   
    fputs(buf, f);
    free(buf);
  } else {
    return -1;
  }
  return 0;
}
Grazie a tutti per la pazienza :)
Ciao.
G.

 come dice Max, per ogni carattere testa strstr(res, "------").
Puoi farne benissimo a meno. Basta contare il numero di caratteri contigui
che incontri.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

     fputs(buf, f);
Non credo tu abbia capito a che cosa serve 'strcspn'. Leggi meglio il
manuale.
Se devi semplicemente cercare la sequenza "------" e stampare su file il
blocco precedente:
  const char* p = strstr(res, "------");
  if( p ) 
  {  fwrite( res, 1, p-res, f ); 
  }
(Manca gestione degli errori.)
M

M
Ottimo, non avevo pensato a fare la differenza tra puntatori.
Questa č la versione modificata (ci sono dei controlli in piů
all'inizio):
int writeAttach(FILE* f, char* messaggio) {
  char* res=NULL;
 
  res=strstr(messaggio, "Content-Transfer-Encoding: base64");
  if (res == NULL) 
    res=strstr(messaggio, "Content-Transfer-Encoding: Base64");
 
  if (res == NULL) return -1; 
 
  res=strstr(res, "Content-Disposition: attachment");  
  if (res == NULL)
    return -1; 
 
  res = strstr(res, "filename=");
 
  if (res != NULL) {
    while (*res != 10 ) res++;
    while (*res != 10 ) res++;
    char* end = strstr(res, "------");
    if (end == NULL) return -1;
 
    size_t toread = (end-res);
    char* buf=malloc(toread+1);
    strncpy(buf, end, toread);   
    fputs(buf, f);
    free(buf);
 
  } else {
    return -1;
  }
  return 0;
}
Ciao e grazie di nuovo.
G.

    strncpy(buf, end, toread);   
ovviamente:
 
  strncpy(buf, res, toread);   
Ciao.
G.

 Altre idee?
salvarsi il puntatore ritornato da strstr(res, "------") cosi da non 
doverlo ricercare ad ogni iterazione sarebbe un ottima cosa in effetti...


Non mi sembra necessario bufferare neanche
lě input , visto che non fai elaborazioni: la butto li' :
// Return : numero byte scritti o un negativo per errore
int writeAttach(FILE* fp, char* messaggio)
{
   char* pStart;
   char* pEnd;
   size_t    len;
    if (NULL == (pStart=strstr(messaggio,"filename=")
    {
        return(-1);
    }
     // salta due linee vuote
     while (*pStart != 0x0A) pStart++;
     while (*pStart != 0x0A) pStart++;
      if(NULL == (pEnd=  strstr(pStart, "------"))
      {
            pEnd= pStart+strlen(pStart);
        }
        len=(size_t)(pEnd-pStart);
        return( fwrite(pStart, len,  sizeof(char), fp);
}
Piu' veloce di cosi'......
bye

Refuso....:-(
// Return : numero byte scritti o un negativo per errore
 int writeAttach(FILE* fp, char* messaggio)
 {
   char* pStart;
   char* pEnd;
   size_t    len;
    if (NULL == (pStart=strstr(messaggio,"filename=")
    {
        return(-1);
    }
     // salta due linee vuote
     while (*pStart != 0x0A) pStart++;
     while (*pStart != 0x0A) pStart++;
    pEnd=pStart;
    len=0;
     while(1)
    {
           char* pTmp;
           if(NULL == (pTmp=  strstr(pEnd, "------"))
           {
                break;   /* end */
            }
            len  +=  (pTmp-pEnd);
            pEnd=pTmp;
      }
      (len)?  return( fwrite(pStart, len,  sizeof(char), fp) : return(-2) ;
 }