Ancora problemi con file

di il
28 risposte

Ancora problemi con file

Salve a tutti
ho scritto il seguente codice ma mi da problemi e non riesco a capire come correggerli
qualcuno e disposto ad aiutarmi?
ringrazio anticipatamente chiunque mi dia una mano.
il codice è il seguente:
// esperimento file.cpp : definisce il punto di ingresso dell'applicazione console.
//

#include "stdafx.h"
#include "windows.h"
#include <iostream>
using std::cout;
using std::cin;
using namespace std;
//using std::end1;
int _tmain(int argc, _TCHAR* argv[])
{
	cout << "esperimento di apertura, lettura di un file utilizzando gli handle\n";
	cout << "il nome del file per il momento è costante.\n";
	cout << "fase 1 APERTURA FILE esito : ";
	HANDLE hesp;
	DWORD  letti, scritti, posizione; 
    char   buff[75];
	int ok = 0;
	hesp = CreateFile("a:esempio.TXT",     // apre esempio.TXT 
                       GENERIC_READ,                 // apre per lettura 
                       0,                            // non condividere
                       NULL,                         // no security 
                       OPEN_EXISTING,                // solo file esistenti 
                       FILE_ATTRIBUTE_NORMAL,        // file normale
                       NULL);                        // no attr. template error C2664: 'CreateFileW': impossibile convertire il parametro 1 da 'const char [14]' a 'LPCWSTR'
	// quando vado a vedere la funzione mi dice che può anche essere null 

if (hesp == INVALID_HANDLE_VALUE) 
  { 
    ErrorHandler("Could not open esempio.");  // process error mi da error C3861: 'ErrorHandler': identificatore non trovato
	cout << "errore\n";
	return 22;
  } 
cout << "positivo\n";
cout << "fase 2 LETTURA FILEB esito;";

do
{
   ReadFile(hesp, buff, 75, &letti, NULL);
    if (hesp == INVALID_HANDLE_VALUE) 
	  { cout << "errore in lettura\n"; return 22;}
    if (ok == 0)
      { cout << "ok\n";
        ok++;
      }
	cout << buff << '\n';
}
   while ( letti == 75);
   cout << "file finito\n";
   CloseHandle(hesp);
	return 0;
}
il compilatore,visual c++ 2008 express edition
, mi restituisce quanto segue:
1>------ Inizio compilazione: Progetto: esperimento file, Configurazione: Debug Win32 ------
1>Compilazione in corso...
1>esperimento file.cpp
1>h:\compilatore mio\esperimenti\esperimento file\esperimento file\esperimento file.cpp(26) : error C2664: 'CreateFileW': impossibile convertire il parametro 1 da 'const char [14]' a 'LPCWSTR'
1> I tipi a cui si punta sono privi di relazioni. La conversione richiede reinterpret_cast, cast di tipo C o cast di tipo funzione
1>h:\compilatore mio\esperimenti\esperimento file\esperimento file\esperimento file.cpp(31) : error C3861: 'ErrorHandler': identificatore non trovato
1>Il log di compilazione è stato salvato in 'file://h:\compilatore mio\esperimenti\esperimento file\esperimento file\Debug\BuildLog.htm'
1>esperimento file - 2 errore/i, 0 avviso/i
========== Compilazione: 0 completate, 1 non riuscite, 0 aggiornate, 0 ignorate ==========

28 Risposte

  • Re: Ancora problemi con file

    Ciao smalldragon,
    Sono un pò arrugginito su queste cose per cui non mi lancio in spiegazioni, comunque il primo errore di copmpilazione è qui:
    
    hesp = CreateFile("a:esempio.TXT", 
    
    devi aggiungere una 'L'
    
    hesp = CreateFile(L"a:esempio.TXT", 
    

    Oppure imposti nelle proprietà del progetto Character 'Set = Use Multi-Byte Character Set'.
    (e poi nel percorso manca lo '\' ovvero "a:\\esempio.txt")

    Per il secondo errore semplicemente non hai definito la funzione 'Errorandler'.
  • Re: Ancora problemi con file

    Ma la funzione ErrorHandler non dovrebbe essere definita in windows.h?
    2 curiosità
    1) al posto della stringa costante "a:esempio.TXT" che tipo di variabile debbo mettere
    stringa o una normalissima char[?] o qualche altro tipo di variabile che non conosco.
    2)ma quando esegue
    if (hesp == INVALID_HANDLE_VALUE)

    come faccio a capire che tipo di errore si è verificato?
    esempio :disco non pronto (come da esempio),file non trovato etc etc
  • Re: Ancora problemi con file

    Più che altro: perché non usare le funzioni C o C++ per la gestione dei file?

    Al di la di questo:
    tutte le funzioni API Windows (a eccezione di GetProcAddress()) che in input prendono stringhe sono semplici define delle corrispondenti API che terminano in A (per ansi) o W per Unicode.
    Ad esempio CreateFile è definita come CreateFileA se non sono definite le macro Unicode, altrimenti è definita come CreateFileW.
    VC++ 2008 per default abilita le macro Unicode per cui la chiamata diventa:
    CreateFileW(LPCWSTR ...
    o qualcosa di simile.
    ma la funzione ErrorHandler non dovrebbe essere definita in windows.h?
    Non mi risulta. Si usa GetLastError() per ricavare il codice d'errore, poi con FormatMessage (anche questa duale come FormatMessageA e FormatMessageW) si ricava il messaggio d'errore.
  • Re: Ancora problemi con file

    Puoi scrivere:
    
    wstring s = L"c:\\temp\\myfile.txt";
    hesp = CreateFile(s.c_str(),     // apre esempio.TXT 
    
    Su 'ErrorHandler' definita in Windows.h non so dirti niente.

    Per di capire che errore si è verificato puoi usare GetLastError(). Questo è un esempio di funzione ErrorHAndler che ho trovato in rete e che usa GetLastError. (per usarla devi aggiungere #include <strsafe.h>)
    
    void ErrorHandler(LPTSTR lpszFunction) 
    { 
        // Retrieve the system error message for the last-error code.
    
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError(); 
    
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0, NULL );
    
        // Display the error message.
    
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
            (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); 
        StringCchPrintf((LPTSTR)lpDisplayBuf, 
            LocalSize(lpDisplayBuf) / sizeof(TCHAR),
            TEXT("%s failed with error %d: %s"), 
            lpszFunction, dw, lpMsgBuf); 
        MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); 
    
        // Free error-handling buffer allocations.
    
        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
    }
    
  • Re: Ancora problemi con file

    Quindi se ho capito bene usando la GetLastError() e confrottando quello che mi ritorna con una tabella degli errori di windows posso gestirmi tutti gli errori che voglio e come voglio.
    ho capito bene?
    io invece pensavo che fosse obbligatoria la routine ErrorHandler.
    c'è un modo per settare l'ultimo errore a zero cosi ad inizio programma evito che per sbaglio quando uso GetLastError() mi restituisca l'errore di un altro processo?
  • Re: Ancora problemi con file

    Non uso le funzioni del c o del c++ preferendo le api perchè ho una formazione di programmatore assembler, la quale adoro, e tra catch try e tutti quegli oggetti nascosti che tengono le funzioni mi ci perdo.
  • Re: Ancora problemi con file

    Puoi usare SetLastError().
    Comunque GetLastError() è garantita per essere thread safe (se due thread danno errori diversi, ogni thread avrà il suo codice d'errore), tuttavia il recupero del codice di errore deve avvenire subito: due chiamate in sequenza per due errori in sequenza nello stesso thread danno codici diversi (ovviamente).
    A ogni modo non c'è un grande vantaggio tra l'usare le API del sistema operativo e le API del C per quanto riguarda i file, tra l'altro il C è appena sopra l'assembly come tipologia di linguaggio. Il C++ (che ha il try catch e tutti quegli oggetti nascosti di cui parli) è sopra il C (che è e rimane un linguaggio procedurale, non a oggetti).
  • Re: Ancora problemi con file

    La funzione SetLastError() la trovo sempre nel file include <strsafe.h> o in qualche altro file di include?
  • Re: Ancora problemi con file

    E' una API Windows, quindi windows.h
  • Re: Ancora problemi con file

    Sono riuscito a leggere il mio bravo file grazie hai vostri aiuti ma notavo che quando andavo a visualizzare la riga che leggevo venivano visualizzati anche caratteri spazzatura.
    da profano del c++ mi chiedevo 2 cose:
    1)da dove venivano questi caratteri spazzatura visto che ogni riga e formattata alla lunghezza del buffer di lettura.
    2)come posso evitare di leggere questi caratteri spazzatura
    posto il codice cosi potete vedere se c'è qualche errore che involontariamente o commesso.
    inoltre, se volete, copiatevi i codici di errore che sono riuscito a trovare vi potranno essere utili.
    // esperimento file.cpp : esempio di apertura e lettura di un file
    #include "stdafx.h"
    #include "windows.h"
    #include <iostream>
    #include <string>
    using std::cout;
    using std::cin;
    using namespace std;
    //using std::end1;
    int _tmain(int argc, _TCHAR* argv[])
    {
        SetLastError(0);
    	cout << "esperimento di apertura, lettura, scrittura di un file utilizzando gli handle\n";
    	cout << "il nome del file per il momento è costante.\n";
    	cout << "fase 1 APERTURA FILE esito : ";
    	HANDLE hesp;
    	DWORD  letti; //, scritti, posizione;
    	DWORD  errore;
    	wstring nomefile = L"a:\\esempio.txt";
        char   buff[80];
    	int ok = 0; // la linea di sotto apre L"a:\\esempio.TXT",apre esempio.TXT 
    	hesp = CreateFile( nomefile.c_str(),                       
                           GENERIC_READ,                 // 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) 
      { 
    	  cout << "errore ";
        errore = GetLastError();
    	switch (errore)
    	      {
    	case 2:    { cout << "file non trovato\n"; break; }
    	case 3:    { cout << "path non trovato\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"; break;}
    	      }
    	return 22;
      } 
    cout << "positivo\n";
    cout << "fase 2 LETTURA FILEB esito;";
    do
    {
    	ReadFile(hesp, buff, 80, &letti, NULL);
        if (hesp == INVALID_HANDLE_VALUE) 
    	  { 
    		   cout << "errore ";
        errore = GetLastError();
    	switch (errore)
    	      {
    	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"; break;}
    	      }
    		return 22;
    	   }
        if (ok == 0)
          { cout << "ok\n";
            ok++;
          }
    	cout << buff;// << '\n';
    }
       while ( letti == 80);
       cout << "file finito\n";
       CloseHandle(hesp);
    	return 0;
    }
    

    siccome volevo fare due funzioni apri_file e leggi_file
    mi chiedevo come potevo far diventare la riga HANDLE hesp; un parametro.
    io l'avevo pensata cosi:
    int apri_file( handle ???<che non so come codificare>,const wstring);
    naturalmente questa e solo un idea.
    ringrazio anticipatamente tutti coloro che mi aiuteranno
  • Re: Ancora problemi con file

    1) Dal fatto che non hai azzerato il buffer. Puoi farlo in fase di dichiarazione con :
    char buff[80] = { 0 }; (sintassi obbligatoria)
    oppure con
    memset(buff,0,80)
    negli altri casi.

    2) Non li eviti, semplicemente gli ignori. ReadFile() ti fornisce il numero di caratteri letti che può essere inferiore a quelli passati. Con quel valore tronchi il buffer ponendo a zero la locazione.
    buff[letti] = 0;

    Semmai una apri_file() non riceve l'handle ma lo restituisce.
    I prototipi più o meno sono simili a questi.

    HANDLE apri_file(const wstring name, int open_mode);
    int leggi_file(HANDLE hesp, char* buff, int len_buff);
  • Re: Ancora problemi con file

    La prima funzione va bene e si risolverebbe il problema dell'eventuale errore inserendo nella chiamata un parametro fittizio.
    pero la seconda non va bene int leggi_file(HANDLE hesp, char* buff, int len_buff);
    perchè cosi come è si leggerebbe sempre lo stesso file in questo caso l'handle dovrebbe essere passato.
    non è che si potrebbe fare int leggi_file(HANDLE *hesp, char* buff, int len_buff);
  • Re: Ancora problemi con file

    Non c'è nessun parametro fittizio, semplicemente passi un intero per stabilire se il file lo vuoi aprire in lettura, scrittura o altro.

    No, non leggi sempre lo stesso file. Pur avendo lo stesso nome le due hesp sono diverse, in quanto occupano spazio diverso sullo stack e non hanno niente a che vedere l'una con l'altra. Puoi chiamarla my_file se ti confonde le idee. Ricorda che ogni chiamata a funzione crea un proprio stack indipendente dalla chiamante.
  • Re: Ancora problemi con file

    Ok penso di aver capito
    stavo facendo la prima funzione apri_file
    ma il linker mi da questo errore
    1>------ Inizio compilazione: Progetto: esperimento file, Configurazione: Debug Win32 ------
    1>Compilazione in corso...
    1>esperimento file.cpp
    1>Collegamento in corso...
    1>esperimento file.obj : error LNK2019: riferimento al simbolo esterno "void * __cdecl apri_file(class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >,int,int)" (?apri_file@@YAPAXV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@HH@Z) non risolto nella funzione _wmain
    1>H:\compilatore mio\esperimenti\esperimento file\Debug\esperimento file.exe : fatal error LNK1120: 1 esterni non risolti
    1>Il log di compilazione è stato salvato in 'file://h:\compilatore mio\esperimenti\esperimento file\esperimento file\Debug\BuildLog.htm'
    1>esperimento file - 2 errore/i, 0 avviso/i========== Compilazione: 0 completate, 1 non riuscite, 0 aggiornate, 0 ignorate ==========
    credo di aver capito che la definizione con HANDLE della funzione non sia corretta.
    se cosi fosse come faccio ad ottenere l'handle del file?
    il codice e il seguente:
    #include "stdafx.h"
    #include "windows.h"
    #include <iostream>
    //#include "strsafe.h"
    #include <string>
    using std::cout;
    using std::cin;
    using namespace std;
    HANDLE apri_file(wstring,int,int);
    int _tmain(int argc, _TCHAR* argv[])
    {
        SetLastError(0);
    	cout << "esperimento di apertura, lettura, scrittura di un file utilizzando gli handle\n";
    	cout << "il nome del file per il momento è costante.\n";
    	cout << "fase 1 APERTURA FILE esito : ";
    	HANDLE hesp;
    	DWORD  letti; //, scritti, posizione;
    	DWORD  errore;
    	wstring nomefile = L"a:\\esempio.txt";
    	int open_mode,err;
    	char   buff[80] = {0};
    	int ok = 0;
    	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 << "positivo\n";
    cout << "fase 2 LETTURA FILEB esito;";
    do
      {
    	ReadFile(hesp, buff, 80, &letti, NULL);
        if (hesp == INVALID_HANDLE_VALUE) 
    	  { 
    		   cout << "errore ";
        errore = GetLastError();
    	switch (errore)
    	      {
    	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 22;
    	  }
        if (ok == 0)
          { cout << "ok\n";
            ok++;
          }
    	buff[letti-1]=0;
    	cout << buff;// << '\n';
    	memset(buff,0,80);
      }
       while ( letti == 80);
       cout << "\nfile finito\n";
       CloseHandle(hesp);
    	return 0;
    //}
     HANDLE apri_file( wstring nomefile,int open_mode,int err);
          {
    		  DWORD  errore;
    		  switch (open_mode)
    		        {
    		          case 1:
    					      {
                                CreateFile( nomefile.c_str(),  // apre esempio.TXT 
                                                GENERIC_READ,  // apre per lettura 
                                                           0,  // non condividere
                                                        NULL,  // no security 
                                               OPEN_EXISTING,  // solo file esistenti 
                                       FILE_ATTRIBUTE_NORMAL,  // file normale
                                                       NULL);  // no attr.
    							 break;
    						  }
                      case 2:
    					      {
                                CreateFile( nomefile.c_str(),  // apre esempio.TXT 
                                               GENERIC_WRITE,  // apre per lettura 
                                                           0,  // non condividere
                                                        NULL,  // no security 
                                               OPEN_EXISTING,  // solo file esistenti 
                                       FILE_ATTRIBUTE_NORMAL,  // file normale
                                                       NULL);  // no attr.
    							 break;
    						  }
                      case 3:
    					      {
                                CreateFile( nomefile.c_str(),  // apre esempio.TXT 
                                GENERIC_READ | GENERIC_WRITE,  // apre per lettura 
                                                           0,  // non condividere
                                                        NULL,  // no security 
                                               OPEN_EXISTING,  // solo file esistenti 
                                       FILE_ATTRIBUTE_NORMAL,  // file normale
                                                       NULL);  // no attr.
    							 break;
    						  }
    				  default:
    					      {
    							  err=-1;
    							  break;
    						  }
    				}
    				if (err == -1) { return 0; }
    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 0;
      } 
    	  }
    }
Devi accedere o registrarti per scrivere nel forum
28 risposte