Ancora problemi con file

di il
28 risposte

28 Risposte - Pagina 2

  • Re: Ancora problemi con file

    Se non fosse corretta avresti un errore di compilazione non di linking.
    Nel caso in esame il linker non trova la definizione della funzione e il motivo è che hai lasciato un ; di troppo
    
    ...
      CloseHandle(hesp);
       return 0;
    //}
    HANDLE apri_file( wstring nomefile,int open_mode,int err); // <-- questo
          {
            DWORD  errore;
            switch (open_mode)
    ...
    
    Comunque ti faccio notare che in apri_file le varie chiamate che fai a CreateFile non assegnano nessun HANDLE, in più puoi semplificare la chiamata così:
    
    HANDLE apri_file( wstring nomefile,int open_mode,int err)
          {
            DWORD  errore, open_flag;
            HANDLE hesp;
         
            switch (open_mode)
                  {
                    case 1:
                         {
                             open_flag =  GENERIC_READ;                          
                         }
                      break;
                      case 2:
                         {
                             open_flag =  GENERIC_WRITE;                          
                          break;
                        }
                      case 3:
                         {
                             open_flag =  GENERIC_READ | GENERIC_WRITE;                          
                          break;
                        }
                  default:
                         {
                           err=-1;
                           break;
                        }
                }
              if (err == -1) { return 0; }
    
               hesp = CreateFile( nomefile.c_str(),  // apre esempio.TXT
                   open_flag,  // apre per lettura
                   0,  // non condividere
                   NULL,  // no security
                   OPEN_EXISTING,  // solo file esistenti
                   FILE_ATTRIBUTE_NORMAL,  // file normale
                   NULL);  // no attr.
     
             if (hesp == INVALID_HANDLE_VALUE) {
              ... gestione errore.
             }
    
             // hesp va restituito sempre a prescindere che sia valido o no, altrimenti le funzioni successive non possono
             // sapere l'esito della chiamata ad apri_file.
             return hesp; 
    }
    
  • Re: Ancora problemi con file

    Grazie ancora
    a volte non so proprio dove tengo la testa quell'handle non definito!
    il ; invece mi avrebbe fatto perdere almeno una settimana prima di farsi sgamare.
    per la funzione leggi_file penso di potermela cavare da solo.
    l'ultima funzione che dovrei fare e da solo non penso di riuscirci e quella legata al filepointer
    facendo delle ricerche ho trovato la seguente struttura:
    SetFilePointer(handle,
                          LONG lDistanceToMove,
                          PLONG lpDistanceToMoveHigh, 
                          DWORD dwMoveMethod);
    mi chiedevo 3 cose:
    1) c'è una funzione che restituisce il puntatore corrente del file, sai come è in caso di errore potrei rimettere le cose a posto.
    2) che tipo di variabili devo usare per gestire long e plong?
    3) quale è il parametro tra i due che non deve mai essere null?
    il prototipo che vorrei usare in questa funzione è il seguente:
    int posiziona_file(Handle,int nrecord,int lunghezza record,int err)
    il metodo sarebbe unico e cioè dall'inizio del file.
    che ne pensi del prototipo?
  • Re: Ancora problemi con file

    Inizio dal fondo.
    Dipende da cosa hai in mente. Quel prototipo è troppo specifico per un utilizzo general purpose: implica sapere l'esistenza di un dato specifico di tipo record e quanto è grande il che significa che la funzione potrebbe essere non riutilizzabile in altri contesti.
    D'altro canto rendere riutilizzabile la funzione significa inserire la SetFilePointer dentro un'altra funzione (magari presettando il terzo parametro a NULL). Insomma, se hai una serie di files strutturati in un certo modo una funzione specifica può andare bene, altrimenti potresti dover riscriverla per adattarla a diversi contesti.

    3) Premesso che NULL == 0, tutti possono essere NULL o 0 (come si evince dai parametri su
    )
    Diciamo che se - lpDistanceToMoveHigh - non è NULL, il suo valore (derefenziato) viene sommato a lDistanceToMove. Questo per poter accedere a offest superiori se i files sono superiori a circa 4GB. Se i tuoi files sono minori di 4GB puoi mettere lpDistanceToMoveHigh a NULL senza problemi.

    2) LONG è un typedef per long e PLONG è un typedef per LONG* e quindi long*

    1) Non c'è una siffatta funzione, ma usi direttamente SetFilePointer con lDistanceToMove == 0, eventuale lpDistanceToMoveHigh == NULL se file <= 4GB oppure - long DistanceToMoveHigh = 0 - passando poi il puntatore a DistanceToMoveHigh alla funzione con &DistanceToMoveHigh, infine dwMoveMethod == FILE_CURRENT
  • Re: Ancora problemi con file

    Quindi se ho capito bene quando la funzione andrebbe in errore dovrei far puntare il file all'inizio del file.
    il tipo LONG la uso come se fosse una normale signed int oppure si usa con comandi che non conosco?
    c'è un sistema per capire quando una variabile LONG assume un valore superiore al suo range?
    cosi nel caso avesse superato il suo range potrei sommare la differenza all'altra variabile LONG?
    la funzione non andrebbe bene solo con i file a record variabile.
    vorra dire che ne farò 2 una cosi come te lo descritta e l'altra sfruttando quella che c'è con l'aggiunta degli errori.
    visto che comunque per implementare la funzione debbo passare per quella di base vorra dire che non la butterò.
    a proposito della funzione apri_file, avevo cantato vittoria troppo presto!.
    quando faccio
    return (hesp) // hesp definita come handle  
    il compilatore mi dice che non può convertire da "HANDLE" a "INT"
    la funzione e definita così:
    HANDLE apri_file( wstring nomefile,int open_mode,int err); // se non metto il ; si incazza
  • Re: Ancora problemi con file

    smalldragon ha scritto:


    quindi se ho capito bene quando la funzione andrebbe in errore dovrei far puntare il file all'inizio del file.
    E' una scelta tua.
    
    SetFilePointer(hesp,0,NULL,FILE_BEGIN); // riporta il file pointer a inizio file.
    
    SetFilePointer(hesp,0,NULL,FILE_CURRENT); // restituisce la posizione corrente del file pointer
    
    SetFilePointer(hesp,0,NULL,FILE_END); // posiziona il file pointer alla fine del file.
    
    Di solito se c'è un errore si chiude il file. Tanto alla successiva riapertura il file pointer è posizionato all'inizio per default.
    il tipo LONG la uso come se fosse una normale signed int oppure si usa con comandi che non conosco?
    Una signed int.
    
    LONG qualcosa = 10;
    PLONG pqualcosa = &qualcosa.
    
    c'è un sistema per capire quando una variabile LONG assume un valore superiore al suo range?
    cosi nel caso avesse superato il suo range potrei sommare la differenza all'altra variabile LONG?
    No. Ne il C nel Il C++ hanno un sistema simile a quello del registro FLAGS (dico bene?) dell'assembly (e che a volte farebbe comodo). Il massimo che si può fare è usare un long long.
    
    long long offset = valore;
    long lowOffset = valore & 0x00000000FFFFFFFF;
    long highOffset = valore & 0xFFFFFFFF00000000;
    
    Se highOffest != 0 hai sforato il limite.
    Personalmente però ti consiglio SetFilePointerEx() per evitare simili problemi.

    ad esempio:
    
    
    LARGE_INTEGER in;
    in.QuadPart=offset_to_move; // offest_to_move può essere sia a 32 sia a 64 bit
    LARGE_INTEGER out;
    out.QuadPart=0;
    if (::SetFilePointerEx(hesp,in,&out,dwMoveMethod) == 0) {
        // gestione errore
    }
    return out.QuadPart; // restituisce l'intero a 64 bit
    
    return out.LowPart; // restituisce l'intero a 32 bit.
    
    a proposito della funzione apri_file, avevo cantato vittoria troppo presto!.
    quando faccio
    return (hesp) // hesp definita come handle  
    il compilatore mi dice che non può convertire da "HANDLE" a "INT"
    la funzione e definita così:
    HANDLE apri_file( wstring nomefile,int open_mode,int err); // se non metto il ; si incazza
    [/QUOTE]
    Avrai fatto un errore banale. Mostra il codice completo della funzione apri_file.
  • Re: Ancora problemi con file

    Già i flag dell'assembler erano una vera e propria manna.
    per il momento ti posto il codice della apri_file
    HANDLE apri_file( wstring nomefile,int open_mode,int err);
          {
    		  DWORD  errore,open_flag;
    		  HANDLE hesp;
    		  switch (open_mode)
    		        {
    		          case 1: {
                                open_flag = GENERIC_READ;
    							 break;
    						  }
                      case 2: {
                                open_flag = GENERIC_WRITE;
    							 break;
    						  }
                      case 3: {
                                open_flag = GENERIC_READ | GENERIC_WRITE;
    							break;
    						  }
    				  default: {
    							  err=-1;
    							  break;
    						  }
    				}
    				if (err == -1) { return hesp; }
    				hesp = CreateFile (nomefile.c_str(),
    					               open_flag,
    						0,
    						NULL,
    						OPEN_EXISTING,
    						FILE_ATTRIBUTE_NORMAL,
    						NULL);
    if (hesp == INVALID_HANDLE_VALUE) 
      { 
    	  err=-2;
    	  cout << "errore ";
        errore = GetLastError();
    	switch (errore)
    	      { // al posto del messaggio di errore in fase definitiva mettere un codice nella variabile err.
    	         case 2:    { cout << "file non trovato\n"; break; }
    	         case 3:    { cout << "path non trovato\n"; break; }
    	        case 21:   { cout << "inserisci il disco e rilancia il programma\n"; break; }
    	        case 26:   { cout << "disco non dos o non formattato\n"; break; }
    	        case 30:   { cout << "lettura\n"; break; }
    	        case 31:   { cout << "disco non funzionante\n"; break; }
    	       case 108:  { cout << "disco in uso da un altro processo\n"; break; }
    	       case 110:  { cout << "apertura\n"; break; }
    	      case 1123: { cout << "interno al disco\n"; break; }
    	      case 1124: { cout << "interno al disco\n"; break; }
    	      case 1125: { cout << "interno al disco\n"; break; }
    	      case 1392: { cout << "file danneggiato\n"; break; }
    	      case 1393: { cout << "disco danneggiato\n"; break; }
    	        default: { 
    		         cout << "sconosciuto\n";
    				 cout << "codice di errore rilevato = " << errore << "\n";
    				  break;
    		             }
    	      }
    	err=errore * (-1);
    	return hesp;
      } 
    return hesp;
    	  }
  • Re: Ancora problemi con file

    A parte quel ; a cui sembri affezionato ( )
    
    HANDLE apri_file( wstring nomefile,int open_mode,int err); // <-- sempre questo
         {
            DWORD  errore,open_flag;
            HANDLE hesp;
    ...
    
    l'unica linea dubbia è questa:
    
    if (err == -1) { return hesp; }
    

    subito dopo lo switch.
    In quel punto hesp ha valore casuale in quanto la CreateFile le assegna un valore subito dopo.
    O fai:
    
    if (err == -1) { return INVALID_HANDLE_VALUE; }
    

    oppure inizializzi hesp prima della CreateFile al valore di default INVALID_HANDLE_VALUE.
    Se lo switch è superato senza problemi sarà la CreateFile ad assegnare il valore corretto a hesp o mantenerlo INVALID_HANDLE_VALUE.
  • Re: Ancora problemi con file

    Se ho capito bene
    nella SetFilePointerEx
    LARGE_INTEGER liDistanceToMove = numero di byte di cui mi voglio spostare
    PLARGE_INTEGER lpNewFilePointer = vecchio puntatore + numero di byte di cui mi voglio spostare.
    mentre nella SetFilePointer
    PLARGE_INTEGER:LARGE_INTEGER = numero di byte di cui mi voglio spostare
    cioè PLARGE_INTEGER e LARGE_INTEGER rappresentano un unico numero
    ho capito bene oppure o scambiato fischi per fiaschi?
  • Re: Ancora problemi con file

    Se levo il ";" al quale sembro essere affezionato
    il compilatore si arrabbia dandomi
    1>h:\compilatore mio\esperimenti\esperimento file\esperimento file\esperimento file.cpp(76) : error C2601: 'apri_file': definizioni di funzioni locali non valide
    e non mi da altri errori.
    mentre se lo rimetto non mi da l'errore sopracitato ma mi da gli errori di conversione tra HANDLE e INT in tutte le parti dove c'è la return.
    HANDLE apri_file( wstring nomefile,int open_mode,int err);
          {
    		  DWORD  errore,open_flag;
    		  HANDLE hesp;
    		  switch (open_mode)
    		        {
    		          case 1: {
                                open_flag = GENERIC_READ;
    							 break;
    						  }
                      case 2: {
                                open_flag = GENERIC_WRITE;
    							 break;
    						  }
                      case 3: {
                                open_flag = GENERIC_READ | GENERIC_WRITE;
    							break;
    						  }
    				  default: {
    							  err=-1;
    							  break;
    						  }
    				}
    				if (err == -1) { 
    					hesp = INVALID_HANDLE_VALUE;
    					return INVALID_HANDLE_VALUE;
    					//return hesp; }
    				hesp = CreateFile (nomefile.c_str(),
    					               open_flag,
    								   0,
    								   NULL,
    								   OPEN_EXISTING,
    								   FILE_ATTRIBUTE_NORMAL,
    								   NULL);
    if (hesp == INVALID_HANDLE_VALUE) 
      { 
    	  err=-2;
    	  cout << "errore ";
        errore = GetLastError();
    	switch (errore)
    	      { // al posto del messaggio di errore in fase definitiva mettere un codice nella variabile err.
    	         case 2:    { cout << "file non trovato\n"; break; }
    	         case 3:    { cout << "path non trovato\n"; break; }
    	        case 21:   { cout << "inserisci il disco e rilancia il programma\n"; break; }
    	        case 26:   { cout << "disco non dos o non formattato\n"; break; }
    	        case 30:   { cout << "lettura\n"; break; }
    	        case 31:   { cout << "disco non funzionante\n"; break; }
    	       case 108:  { cout << "disco in uso da un altro processo\n"; break; }
    	       case 110:  { cout << "apertura\n"; break; }
    	      case 1123: { cout << "interno al disco\n"; break; }
    	      case 1124: { cout << "interno al disco\n"; break; }
    	      case 1125: { cout << "interno al disco\n"; break; }
    	      case 1392: { cout << "file danneggiato\n"; break; }
    	      case 1393: { cout << "disco danneggiato\n"; break; }
    	        default: { 
    		         cout << "sconosciuto\n";
    				 cout << "codice di errore rilevato = " << errore << "\n";
    				  break;
    		             }
    	     }
    	err=errore * (-1);
    	hesp = INVALID_HANDLE_VALUE;
    	return hesp;
      } 
    return hesp;
    	  }
    }
  • Re: Ancora problemi con file

    LARGE_INTEGER liDistanceToMove = numero di byte di cui mi voglio spostare
    PLARGE_INTEGER lpNewFilePointer = posizione del file pointer dopo lo spostamento.
    SetFilePointerEx() ha una più semplice gestione di un eventuale errore e non ha il problema di un eventuale overflow di un long, dove invece con SetFilePointer() sei costretto a controllare se il long sfora, se si cosa fare in caso, e come procedere in casi di errore (come mostrato nel link di SetFilePointer() )
    Con SetFilePointerEx() imposti di quanto ti vuoi spostare e come, e se la pretesa non è assurda restituisce la nuova posizione del file pointer. In base alla variabile di uscita (long o long long (int64) ) restituisci il parametro corretto; la QuadWord se la variabile è 64 bit o LowPart se la variabile e 32 bit.
  • Re: Ancora problemi con file

    smalldragon ha scritto:


    se levo il ";" al quale sembro essere affezionato
    il compilatore si arrabbia dandomi
    1>h:\compilatore mio\esperimenti\esperimento file\esperimento file\esperimento file.cpp(76) : error C2601: 'apri_file': definizioni di funzioni locali non valide
    e non mi da altri errori.
    mentre se lo rimetto non mi da l'errore sopracitato ma mi da gli errori di conversione tra HANDLE e INT in tutte le parti dove c'è la return.
    Quell'errore sta a indicare che togliendo il ; stai definendo una funzione all'interno di un'altra funzione, il che è vietato in C. Se aggiungi il ; il compilatore incorpora il codice della funzione all'interno del main e tenta la conversione tra HANDLE e int.
    In pratica non hai chiuso correttamente il main.
    
      while ( letti == 80);
       cout << "\nfile finito\n";
       CloseHandle(hesp);
       return 0;
    
    //}  // togli il commento a questa grafa.
    
    HANDLE apri_file( wstring nomefile,int open_mode,int err)
          {
            DWORD  errore;
            switch (open_mode)
                  {
                    case 1:
    
    
  • Re: Ancora problemi con file

    Avevo commesso un gran casino con quelle parentisi graffe.
    non era l'unica a star fuori posto!
    ma LARGE_INTEGER liDistanceToMove
    PLARGE_INTEGER lpNewFilePointer
    se ho capito bene le due variabili sono dello stesso tipo o sbaglio?
    quindi:
    long long comodo;
    int numero_record,dimrec;
    numero_record = 44; dimrec=80;
    comodo = posizione_file(handle hesp,int numero_record,int dimrec,int err)
          {
            long long spostamento,newpoint;
            spostamento = numero_record * dimerec;
    SetFilePointerEx(hesp,spostamento,newpointer,FILE_BEGIN );
    //gestione errori
    return newpointer;
    }
    grosso modo va bene questa struttura?
  • Re: Ancora problemi con file

    No. A parte che hai definito una funzione presumibilmente all'interno di un'altra funzione (come per sbaglio prima), Il C prevede regole sintattiche più stringenti dell'assembly. Se SetFilePointerEx() prevede come parametro d'ingresso un LARGE_INTEGER, quello gli devi dare, non un long long.
    Confronta il codice che avevo postato io al riguardo e il tuo.
  • Re: Ancora problemi con file

    Guarda un pò se ho fatto le procedure bene specialmente quella di posizione del puntatore del file.
    // esperimento file2.cpp : definisce il punto di ingresso dell'applicazione console.
    //
    #include "stdafx.h"
    #include "windows.h"
    #include <iostream>
    #include <string>
    using std::cout;
    using std::cin;
    using namespace std;
    HANDLE apri_file(wstring,int,int);
    int leggi_file(handle,const char*,int);
    int posiziona_record(HANDLE,int,int);
    int _tmain(int argc, _TCHAR* argv[])
       {
         SetLastError(0);
            HANDLE  hesp;
            DWORD   letti; 
            DWORD   errore;
            wstring nomefile;
            int open_mode,err,i;
            int lrecord=80;
    	char   buff[80] = {0};
            cout << "esperimento di lettura di un file\n";
            cout << "dopo l'apertura saranno stampati i record pari\n";
            cout << "inserisci il nome del file : ";
            cin >> nomefile;
            cout << "\n";
    	open_mode=1;
    	err=0;
    	hesp = apri_file (nomefile,open_mode,0);
    	if (err == -1)
    	  {
    		  cout << "errore di parametri nella apertura del file\n";
    			  return 0;
    	  }
            cout >> "apertura ok\n";
            i=1;
            while ( err == 0 )
                 {
                   err=posiziona_record(hesp,i,80);
                   if (err == 1)
                     {
                      cout >> " errore posizionamento passata la fine del file\n";
                      goto uscita_emergenza;
                     }
                   err=leggi_file(hesp,buff,80);
                   if (err == 1)
                     {
                      cout >> "errore in lettura file\n";
                      goto uscita_emergenza;
                     }
                   i=i+2;
                   uscita_emergenza:
                 }
            cout >> "lettura finita\n";
            CloseFile(hesp);
       }
     HANDLE apri_file( wstring nomefile,int open_mode,int err)
           {
             DWORD  errore,open_flag;
             HANDLE hesp;
             switch (open_mode)
                   {
                    case 1: {
                             open_flag = GENERIC_READ;
                             break;
                            }
                    case 2: {
                             open_flag = GENERIC_WRITE;
                             break;
                            }
                    case 3: {
                             open_flag = GENERIC_READ | GENERIC_WRITE;
                             break;
                            }
                    default: {
                               err=1;
                               break;
                             }
                   }
             if (err == 1) { return INVALID_HANDLE_VALUE; }
             hesp = CreateFile (nomefile.c_str(),
                                       open_flag,
                                               0,
                                            NULL,
                                   OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                                             NULL);
             if (hesp == INVALID_HANDLE_VALUE) 
               { 
                 cout << "errore ";
                 errore = GetLastError();
                 switch (errore) // al posto del messaggio di errore in fase definitiva mettere un codice nella variabile err.
                       {
                         case 2:    { cout << "file non trovato\n"; break; }
                         case 3:    { cout << "path non trovato\n"; break; }
                         case 6:    { cout << "handle non corretto\n"; break; }
                        case 21:   { cout << "inserisci il disco e rilancia il programma\n"; break; }
                        case 26:   { cout << "disco non dos o non formattato\n"; break; }
                        case 30:   { cout << "lettura\n"; break; }
                        case 31:   { cout << "disco non funzionante\n"; break; }
                        case 108:  { cout << "disco in uso da un altro processo\n"; break; }
                        case 110:  { cout << "apertura\n"; break; }
                        case 1123: { cout << "interno al disco\n"; break; }
                        case 1124: { cout << "interno al disco\n"; break; }
                        case 1125: { cout << "interno al disco\n"; break; }
                        case 1392: { cout << "file danneggiato\n"; break; }
                        case 1393: { cout << "disco danneggiato\n"; break; }
                          default: { 
                                    cout << "sconosciuto\n";
                                    cout << "codice di errore rilevato = " << errore << "\n";
                                    break;
                                   }
                       }
                 err=errore;
                 hesp = INVALID_HANDLE_VALUE;
                 return hesp;
               } 
             return hesp;
           }
    int leggi_file(hesp,buff,int record)
       {
         ReadFile(hesp, buff, 80, &letti, NULL);
         if (hesp == INVALID_HANDLE_VALUE) 
           { 
             cout << "errore ";
             errore = GetLastError();
             switch (errore)
                   {
                        case 6: { cout << "handle non corretto\n"; break; }
                       case 30: { cout << "lettura\n"; break; }
                       case 31: { cout << "disco non funzionante\n"; break; }
                      case 108: { cout << "disco in uso da un altro processo\n"; break; }
                     case 1123: { cout << "interno al disco\n"; break; }
                     case 1124: { cout << "interno al disco\n"; break; }
                     case 1125: { cout << "interno al disco\n"; break; }
                     case 1392: { cout << "file danneggiato\n"; break; }
                     case 1393: { cout << "disco danneggiato\n"; break; }
                       default: 
                               { 
                                 cout << "sconosciuto in fase di lettura\n"; 
                                 cout << "codice di errore rilevato = " << errore << "\n";
                                 break;
    			   }
    	      }
                    return 1;
           }
           return 0;
       }
    // sotto c'è la procedura di posizionamento nel file ho considerato il record di 80 caratteri
    int posiziona_record(hesp,i,lrecod);
       {
         LARGE_INTEGER in;
           in.QuadPart = i * lrecord;
         LARGE_INTEGER out;
           out.QuadPart = 0;
         DWORD ERRORE;
         SetFilePointerEX(hesp,in,&out,FILE_BEGIN);
         if (::SetFilePointerEx(hesp,in,&out,FILE_BEGIN) == 0)
           {
             ERRORE = GetLastError()
             cout << "N. errore = " << errore; // devo ancora scoprire quali codici mi servono per fare 
                                                            //una gestione errori ben fatta
             cout << "\n";
             return 1
           }
             return 0;
        }
    
    
    speriamo che per gravita e numero di errori sono migliorato!
    le routine le devo ancora eseguire
Devi accedere o registrarti per scrivere nel forum
28 risposte