2008-10-02 19 views
26

Piszę bibliotekę C, która odczytuje plik do pamięci. Pomija pierwsze 54 bajty pliku (nagłówek), a resztę odczytuje jako dane. Używam fseek do określenia długości pliku, a następnie używam fread do odczytu w pliku.Dlaczego wczesna frekwencja osiąga EOF?

Pętla działa jeden raz, a następnie kończy się, ponieważ został osiągnięty EOF (brak błędów). Na końcu, bytesRead = 10624, ftell (stream) = 28726, a bufor zawiera 28726 wartości. Spodziewam się, że fread odczyta 30 000 bajtów, a pozycja pliku na 30054, gdy osiągnięty zostanie EOF.

C nie jest moim ojczystym językiem, więc podejrzewam, że mam gdzieś głupi błąd początkującego.

Kod jest następujący:

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; 
} 

W zależności od używanego odniesienia, to całkiem oczywiste, że dodanie „b” do flagi trybu jest odpowiedzią. Szuka nominacji na znaczek kości. :-)

This reference mówi o tym w drugim akapicie, drugie zdanie (choć nie w ich tabeli).

MSDN nie omawia flagi binarnej do połowy strony.

OpenGroup wspomina o istnieniu znacznika "b", ale stwierdza, że ​​"nie przyniesie efektu".

+0

Dodałem tag microsoft od fopen_s jest jedynie w języku C RTL członkowskiego co. – user7116

+0

OpenGroup wspomina to: r lub rb - Otwórz plik do odczytu. ... Znak "b" nie ma żadnego efektu, ale jest dozwolony dla zgodności ze standardem ISO C. Napraw swoją edycję. –

+0

Usunąłem tag microsoft. –

Odpowiedz

48

Być może jest to problem w trybie binarnym. Spróbuj otworzyć plik z "r+b" jako trybem.

EDIT: jak zauważono w komentarzu "rb" prawdopodobnie lepsze dopasowanie do swojej pierwotnej intencji od "r+b" otworzy go do odczytu/zapisu i "rb" jest tylko do odczytu.

+0

Pseudo +1 (Nie mam głosów) –

+0

+1 dla Mike'a F i dla mnie. Windows ugryza mnie z + b przez cały czas. – user7116

+0

Proponuję najpierw wypróbować "rb", ponieważ "r + b" otwiera plik do odczytu i zapisu, a jeśli nie zamierzasz pisać do pliku, powinieneś otworzyć go jako tylko do odczytu. –

0

Warto również zauważyć, że samo dodanie binmode.obj do polecenia link zrobi to dla ciebie, gdy otworzy się cały plik.

-1

rozwiązania, na podstawie poprzednich odpowiedzi:

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; 
}