Modo corretto per ottenere dimensioni del file in C

Sto lavorando su un compito in programmazione socket in cui devo inviare un file tra sparc e macchina Linux. Prima di inviare il file in char stream devo ottenere la dimensione del file e dirlo al client. Ecco alcuni dei modi in cui ho cercato di ottenere le dimensioni ma non sono sicuro quale sia quella giusta.

A scopo di test, ho creato un file con contenuto “test” (spazio + (stringa) test)

Metodo 1 – Usare fseeko () e ftello ()

Questo è un metodo che ho trovato su https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+e+ftell()+to+compute+ il + size + di + a + regular + file Mentre fssek () ha il problema di “Impostare l’indicatore di posizione del file su end-of-file, come con fseek (file, 0, SEEK_END), ha un comportamento indefinito per un binario stream “, si dice che fseeko () abbia affrontato questo problema ma funziona solo sul sistema POSIX (che va bene perché l’ambiente che sto usando è sparc e linux)

fd = open(file_path, O_RDONLY); fp = fopen(file_path, "rb"); /* Ensure that the file is a regular file */ if ((fstat(fd, &st) != 0) || (!S_ISREG(st.st_mode))) { /* Handle error */ } if (fseeko(fp, 0 , SEEK_END) != 0) { /* Handle error */ } file_size = ftello(fp); fseeko(fp, 0, SEEK_SET); printf("file size %zu\n", file_size); 

Questo metodo funziona correttamente e ottiene le dimensioni corrette. Tuttavia, è limitato ai soli file regolari. Ho provato a usare il termine “file normale”, ma ancora non lo capisco del tutto. E non so se questa funzione è affidabile per il mio progetto.

    Metodo 2 – Utilizzo di strlen ()

    Dal momento che il max. la dimensione di un file nel mio progetto è 4MB, quindi posso solo chiamare un buffer da 4MB. Dopodiché, il file viene letto nel buffer, e ho provato a usare lo strlen per ottenere le dimensioni del file (o più correttamente la lunghezza del contenuto). Poiché strlen () è portatile, posso invece utilizzare questo metodo? Lo snippet di codice è come questo

     fp = fopen(file_path, "rb"); fread(file_buffer, 1024*1024*4, 1, fp); printf("strlen %zu\n", strlen(file_buffer)); 

    Anche questo metodo funziona e restituisce

     strlen 8 

    Tuttavia, non ho potuto vedere alcun approccio simile su Internet utilizzando questo metodo. Quindi penso che forse ho perso qualcosa o ci sono alcune limitazioni di questo approccio che non ho capito.

    File regolari significa che non è niente di speciale come dispositivo, socket, pipe ecc. Ma file “normale”. Sembra che dalla descrizione dell’attività prima dell’invio sia necessario recuperare la dimensione del file normale. Quindi la tua strada è giusta:

     FILE* fp = fopen(...); if(fp) { fseek(fp, 0 , SEEK_END); long fileSize = ftell(fp); fseek(fp, 0 , SEEK_SET);// needed for next read from beginning of file ... fclose(fp); } 

    ma puoi farlo senza aprire il file:

     #include  #include  #include  struct stat buffer; int status; status = stat("path to file", &buffer); if(status == 0) { // size of file is in member buffer.st_size; } 

    OP può farlo nel modo più semplice in quanto “dimensione massima di un file nel mio progetto è 4MB”.

    Piuttosto che usare strlen() , usa il valore restituito da fread() . stlen() ferma sul primo carattere null, quindi potrebbe riportare un valore troppo piccolo. @Sami Kuhmonen Inoltre, non sappiamo che i dati letti contengano caratteri null, quindi potrebbe non essere una stringa. Aggiungi un carattere null (e alloca +1) se il codice deve utilizzare i dati come stringa. Ma in tal caso, mi aspetto che il file debba essere aperto in modalità testo.

    Si noti che molti sistemi operativi non utilizzano nemmeno la memoria allocata finché non viene scritta.
    Perché Malloc non “consuma” la memoria sul mio computer?

     fp = fopen(file_path, "rb"); if (fp) { #define MAX_FILE_SIZE 4194304 char *buf = malloc(MAX_FILE_SIZE); if (buf) { size_t numread = fread(buf, sizeof *buf, MAX_FILE_SIZE, fp); // shrink if desired char *tmp = realloc(buf, numread); if (tmp) { buf = tmp; // Use buf with numread char } free(buf); } fclose(fp); } 

    Nota: leggere l’intero file nella memoria potrebbe non essere la migliore idea per cominciare.