2008-10-02 15 views
26

Tôi đang viết một thư viện C đọc tập tin vào bộ nhớ. Nó bỏ qua 54 byte đầu tiên của tệp (tiêu đề) và sau đó đọc phần còn lại dưới dạng dữ liệu. Tôi sử dụng fseek để xác định chiều dài của tập tin, và sau đó sử dụng fread để đọc trong tập tin.Tại sao fread tiếp cận EOF sớm?

Vòng lặp chạy một lần và sau đó kết thúc vì đạt được EOF (không có lỗi). Cuối cùng, bytesRead = 10624, ftell (stream) = 28726 và bộ đệm chứa 28726 giá trị. Tôi mong đợi fread để đọc 30.000 byte và vị trí tập tin được 30054 khi đạt được EOF.

C không phải là ngôn ngữ mẹ đẻ của tôi vì vậy tôi nghi ngờ tôi đã có một sai lầm mới bắt đầu câm ở đâu đó.

Mã là như sau:

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

Tùy thuộc vào tham khảo bạn sử dụng, nó khá rõ ràng rằng việc thêm một "b" để cờ chế độ là câu trả lời. Tìm kiếm các đề cử cho huy hiệu xương đầu. :-)

This reference nói về nó trong đoạn thứ hai, câu thứ hai (mặc dù không có trong bảng của họ).

MSDN không thảo luận cờ nhị phân cho đến nửa chừng dưới trang.

OpenGroup đề cập đến sự tồn tại của thẻ "b", nhưng nói rằng "sẽ không có hiệu lực".

+0

tôi thêm thẻ microsoft từ fopen_s chỉ trong C RTL của MS. – user7116

+0

OpenGroup không đề cập đến nó: r hoặc rb - Mở tệp để đọc. ... Ký tự 'b' sẽ không có hiệu lực, nhưng được cho phép theo tiêu chuẩn ISO C. Vui lòng chỉnh sửa chỉnh sửa của bạn. –

+0

Tôi đã xóa thẻ microsoft. –

Trả lời

48

có lẽ đó là vấn đề về chế độ nhị phân. Thử mở tệp bằng "r+b" làm chế độ.

EDIT: như đã nêu trong một chú thích "rb" có thể là một trận đấu tốt hơn để ý định ban đầu của bạn kể từ "r+b" sẽ mở nó để đọc/viết và "rb" là read-only.

+0

Pseudo +1 (Tôi không tham gia biểu quyết) –

+0

+1 cho Mike F và bản thân tôi. Windows luôn luôn cắn tôi + b. – user7116

+0

Tôi khuyên bạn nên thử "rb" trước tiên, vì "r + b" mở tệp tin để đọc và viết, và nếu bạn không có ý định ghi vào tệp, bạn nên tiếp tục mở nó dưới dạng chỉ đọc. –

0

Cũng đáng lưu ý rằng chỉ cần bao gồm binmode.obj vào lệnh liên kết của bạn sẽ làm điều này cho bạn cho tất cả các tệp mở ra.

-1

Một giải pháp, dựa trên các câu trả lời trước:

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