Perché fread raggiunge presto l'EOF?
Domanda
Sto scrivendo una libreria C che legge un file in memoria. Salta i primi 54 byte del file (intestazione) e quindi legge il resto come dati. Uso fseek per determinare la lunghezza del file, quindi uso fread per leggere il file.
Il ciclo viene eseguito una volta e quindi termina perché viene raggiunto l'EOF (nessun errore). Alla fine, bytesRead = 10624, ftell (stream) = 28726 e il buffer contiene 28726 valori. Mi aspetto che fread legga 30.000 byte e che la posizione del file sia 30054 quando viene raggiunto EOF.
C non è la mia lingua madre, quindi sospetto di aver avuto un errore stupido per principianti da qualche parte.
Il codice è il seguente:
const size_t headerLen = 54;
FILE * stream;
errno_t ferrno = fopen_s( &stream, filename.c_str(), "r" );
if(ferrno!=0) {
return -1;
}
fseek( stream, 0L, SEEK_END );
size_t bytesTotal = (size_t)(ftell( stream )) - headerLen; //number of data bytes to read
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-bytesRead,stream);
bytesRead+=result;
}
A seconda del riferimento che usi, è abbastanza evidente che l'aggiunta di una "b" alla modalità flag è la risposta. Cerco nomination per il badge bonehead. : -)
Questo riferimento ne parla nel secondo paragrafo, seconda frase (anche se non nella loro tabella).
MSDN non discute il binario bandiera fino a metà della pagina.
OpenGroup menziona l'esistenza di " b " tag, ma afferma che non deve avere alcun effetto " ;.
Soluzione
forse è un problema in modalità binaria. Prova ad aprire il file con " r + b "
come modalità.
MODIFICA : come indicato in un commento " rb "
è probabilmente una corrispondenza migliore con il tuo intento originale poiché " r + b "
lo aprirà per lettura / scrittura e " rb "
è di sola lettura.
Altri suggerimenti
Vale anche la pena notare che semplicemente l'inclusione di binmode.obj nel comando di collegamento lo farà per te per l'apertura di tutti i file.
Una soluzione, basata sulle risposte precedenti:
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-
bytesRead,stream);
bytesRead+=result;
}