2008-09-28 28 views
8

Rất chỉ cần đặt, tôi có đoạn mã sau:Cuối FILE * con trỏ không bằng kích thước của dữ liệu bằng văn bản

FILE* test = fopen("C:\\core.u", "w"); 
printf("Filepointer at: %d\n", ftell(test)); 
fwrite(data, size, 1, test); 
printf("Written: %d bytes.\n", size); 
fseek(test, 0, SEEK_END); 
printf("Filepointer is now at %d.\n", ftell(test)); 
fclose(test); 

và nó kết quả đầu ra:

Filepointer at: 0 
Written: 73105 bytes. 
Filepointer is now at 74160. 

Tại sao vậy? Tại sao số byte được viết không khớp với con trỏ của tệp?

+2

Tôi khuyên bạn không nên sử dụng đường dẫn kiểu NT trong các đối số fopen(). Windows cũng hỗ trợ các đường dẫn POSIX, có thể di chuyển và không yêu cầu thoát '\'. – Terminus

Trả lời

19

Vì bạn đang mở tệp ở chế độ văn bản, nó sẽ chuyển đổi điểm đánh dấu cuối dòng, chẳng hạn như LF, thành CR/LF.

Điều này có thể xảy ra nếu bạn đang chạy trên Windows (và có thể bạn đang có, với tên tệp của bạn bắt đầu bằng "c:\").

Nếu bạn mở tập tin trong chế độ "wb", tôi nghi ngờ bạn sẽ tìm thấy những con số giống hệt nhau:

FILE* test = fopen("C:\\core.u", "wb"); 

Tiêu chuẩn C99 đã cho biết trong 7.19.5.3 The fopen function:

Chế độ lý luận trỏ đến một chuỗi. Nếu chuỗi là một trong những điều sau, tệp là mở ở chế độ được chỉ định. Nếu không, hành vi là không xác định.

r tập tin văn bản mở để đọc
w truncate để zero chiều dài hoặc tạo tập tin văn bản để viết
a append; mở hoặc tạo tập tin văn bản để viết vào cuối của file
rb tập tin nhị phân mở để đọc
wb truncate để zero chiều dài hoặc tạo tập tin nhị phân để viết
ab append; mở hoặc tạo ra tập tin nhị phân để viết vào cuối của file
r+ mở tập tin văn bản để cập nhật (đọc và viết)
w+ truncate để zero chiều dài hoặc tạo tập tin văn bản để cập nhật
a+ append; mở hoặc tạo tập tin văn bản để cập nhật, viết vào cuối của file
r+b hay rb+ tập tin nhị phân mở để cập nhật (đọc và viết)
w+b hoặc wb+ cắt ngắn để không dài hoặc tạo tập tin nhị phân để cập nhật
a+b hoặc ab+ nối thêm; mở hoặc tạo tệp nhị phân để cập nhật, viết ở cuối tệp

Bạn có thể thấy chúng phân biệt giữa wwb. Tôi không tin rằng việc triển khai được yêu cầu yêu cầu để xử lý hai cách khác nhau nhưng thường là an toàn hơn khi sử dụng chế độ nhị phân cho dữ liệu nhị phân.

+1

Đây là một góc khá tối của ngôn ngữ, tôi sợ. Người ta có xu hướng không biết nó ở đó cho đến khi họ bị cắn bởi nó. Đẹp bắt! – fbrereto

+0

Cần lưu ý rằng POSIX yêu cầu thực hiện ** không ** đối xử với họ khác nhau. –

0

trả về fwrite là gì? thông thường giá trị trả về phải là số byte được ghi. Ngoài ra, ftell() trả lời gì với quyền trước fseek?

Có thể giúp bạn biết hệ điều hành, phiên bản trình biên dịch C và thư viện C nào.

0

Trình tạo kiểu tệp là cookie. Nó không có giá trị. Điều duy nhất bạn có thể sử dụng nó là để tìm kiếm cùng một vị trí trong một tập tin. Tôi thậm chí không chắc chắn nếu ISO C đảm bảo rằng ftell trả về giá trị gia tăng. Nếu bạn không tin điều này, hãy xem xét các chế độ tìm kiếm khác nhau(). Chúng tồn tại chính xác vì vị trí không phải là một bù đắp byte đơn giản.

+0

Vâng, nhưng chúng phải được triển khai * bằng cách nào đó *. Ngay cả khi nó không được chỉ định bởi tiêu chuẩn, các con trỏ tập tin sẽ chỉ đơn giản là bù đắp byte trong nhiều triển khai, do đó, nó quá thái quá để nói rằng nó có "không có giá trị". – Tom

+0

Nó không phải là một cookie. Đó là một bù đắp byte ở chế độ nhị phân. Chế độ văn bản là địa ngục và hầu như không đảm bảo về bất cứ điều gì làm việc ở tất cả, và chỉ đơn giản là không nên được sử dụng. –

+0

@R ..: vui lòng trích dẫn phần của tiêu chuẩn C đảm bảo như vậy. Ngay cả chế độ byte cũng là một phần mở rộng POSIX. – MSalters

0

cửa sổ không thực sự ghi tất cả dữ liệu ra tệp mà không bị xóa và có thể là một fsync. Có lẽ đó là lý do tại sao

Các vấn đề liên quan