2011-05-13 19 views
10

Sto lavorando ad un semplice programma di splitter/merger di file nel linguaggio di programmazione C. Il problema è che, per qualche motivo, fopen restituisce NULL e, a causa di ciò, il mio programma si arresta in modo anomalo all'istruzione fwrite. Come posso risolvere questo?Perché "fopen" restituisce un puntatore NULL?

Ecco il file C:

int SplitFile(char* filename, char* output, size_t size) 
{ 
    char current_file_name[256]; 
    int file_count = 0, i = 0; 
    FILE *file = fopen(filename, "rb"); 
    printf("split %s into chunks of %d named\n", filename, size); 

    if (!file) 
     return E_BAD_SOURCE; 
    else 
    { 
     output = (char *) malloc(size * sizeof(char)); 
     if (output == NULL) 
      return E_NO_MEMORY; 
     else 
     { 
      int bytes_read = 0; 
      FILE *outFile; 
      do 
      { 
       bytes_read = fread(output, sizeof(char), size, file); 
       sprintf(current_file_name, "%s%04lu\n", "part", file_count++); 
       outFile = fopen (current_file_name, "wb"); // THIS RETURNS NULL 
       fwrite(output, sizeof(char), bytes_read, outFile); //CRASHES ON THIS LINE 
      } 
      while (bytes_read > 0) 
       ; 

      //fclose(outFile); 
     } 
    } 
    fclose(file); 
    printf("...\n"); 
    return 0; 
} 
+1

Snarky - verificare il file aperto prima di provare a scrivere. La vera risposta è che probabilmente non hai i permessi del file system o è in un percorso di cartella che non esiste – EnabrenTane

+9

Quale errore è memorizzato in 'errno'? Basta aggiungere 'if (! OutFile) perror (" fopen ");' e lasciare che la libreria ti dica perché ha fallito. :) – sarnold

+0

in errno Sto diventando fopen: Argomento non valido – k787

risposta

9

La cosa giusta da fare è controllare errno quando fopen rendimenti NULL.

Ho intenzione di indovinare che il tuo problema è che stai cercando di scrivere su un filesystem che non consente lo \n nei nomi di file, ma potrebbe anche essere un problema di autorizzazioni.

+1

La cosa più corretta da fare è controllare errno quando fopen restituisce NULL. Probabilmente intendevi fopen invece di fwrite. –

+0

quando commento lo sprint e lo faccio; outFile = fopen ("part000", "wb"); funziona bene – k787

+0

@Windows: Oops! Grazie. – Gabe

0

È fopen per write return NULL nella prima esecuzione?

Ho notato che nel frattempo si mantengono aperti i file per scrivere ma non per chiuderli.

tenta di aggiungere fclose (OUTFILE) dopo fwrite:

outFile = fopen (current_file_name , "wb");  
fwrite(output, sizeof(char), bytes_read, outFile); 
fclose(outFile) 

E 'possibile aprire più file di sistema operativo consente.

+0

sì, ho pensato la stessa cosa e ho chiuso i file, ma non ha funzionato – k787

1

Come ha detto Gabe, il problema è il newline nel nome del file che è illegale in Windows.

Ma perché non si usa semplicemente lo split da GNU Core Utilities. Installato di default su Unices/Linux, può essere scaricato per Windows da GnuWin32 project.

split --suffix-length=4 --numeric-suffixes --bytes=1M - part < filename 
5

Ci sono molte ragioni fopen può tornare NULL tra cui (ma certamente non solo):

  • Il file non esiste
  • Il file viene aperto in una modalità che non lo fa autorizzare altri accessi
  • La rete non funziona
  • Il file esiste, ma non si dispone delle autorizzazioni
  • Un file esiste con il nome che hai dato, ma la directory corrente del processo non è quella che ti aspetti, quindi il relativo percorso non riesce a trovare e aprire il file.

Il modo per scoprire quale è responsabile è scavare nel codice errno.

Tuttavia, solo perché si risolve questo particolare errore non significa che si possa supporre che fopen non restituirà mai NULL. Quando si tratta di operazioni di I/O, il codice deve semplicemente aspettarsi un errore. Non è possibile prevedere il successo delle operazioni di I/O e possono sempre fallire.

+0

cosa dire di rimanere senza spazio? non lo farebbe restituire NULL? (so che hai detto "non limitato a" la mia domanda non è retorica) – Nande

+0

@Nande: 'fopen()' che crea un nuovo file può o non può avere successo su un intero disco. Se la directory non ha bisogno di espandersi (e non sei fuori da inode), può avere successo, ma un seguente 'fwrite()' (** o ** 'fclose()'!) Fallirà. –

1

Significa che il file potrebbe non esistere o si è verificato un errore di autorizzazione durante l'accesso a un file come "Sola lettura" o "Protetto da scrittura", quindi in questi casi fopen restituirà 0 (un puntatore NULL). In caso di successo restituirà un puntatore di file come gestore.

fp=fopen("c:\\ABC.txt", "r"); non può essere lo stesso di fp=fopen("c:\\abc.txt", "r");.

Utilizzare // anziché \\ in un ambiente Linux.

P.S .: Nei nomi dei file sistemi operativi Linux e Unix-like sono maiuscole e minuscole.

0

In Unix, per fopen(), non c'è motivo di anteporre ./ a un nome file passato a fopen().

0

Nel mio caso, stavo leggendo lo stesso file tutto da capo e ho dimenticato di chiuderlo.

Ho usato una funzione per la lettura del file e la ricerca di una corrispondenza e la funzione ha avuto una dichiarazione return; che terminata la funzione prima di fare fclose(fp): D

Problemi correlati