2008-10-23 77 views
45

Bản dịch nào xảy ra khi ghi vào một tệp đã được mở ở chế độ văn bản không xuất hiện ở chế độ nhị phân? Cụ thể trong MS Visual C.Sự khác biệt giữa các tập tin được viết ở dạng nhị phân và văn bản

unsigned char buffer[256]; 
for (int i = 0; i < 256; i++) buffer[i]=i; 
int size = 1; 
int count = 256; 

chế độ nhị phân:

FILE *fp_binary = fopen(filename, "wb"); 
fwrite(buffer, size, count, fp_binary); 

so với chế độ văn bản:

FILE *fp_text = fopen(filename, "wt"); 
fwrite(buffer, size, count, fp_text); 
+0

Động lực cho câu hỏi là tôi muốn khôi phục dữ liệu nhị phân đã vô tình được ghi vào đĩa ở chế độ văn bản – jholl

+0

Liên quan chặt chẽ: http://stackoverflow.com/q/ 11981434/183120 – legends2k

Trả lời

35

Tôi tin rằng hầu hết các nền tảng sẽ bỏ qua tùy chọn "t" hoặc tùy chọn "chế độ văn bản" khi xử lý luồng. Trên cửa sổ, tuy nhiên, đây không phải là trường hợp. Nếu bạn có một cái nhìn tại các mô tả về fopen() chức năng tại địa chỉ: MSDN, bạn sẽ thấy rằng việc xác định "t" tùy chọn sẽ có tác dụng sau:

  • dòng nguồn cấp dữ liệu ('\ n') sẽ được được dịch sang các chuỗi '\ r \ n' trên đầu ra
  • trình tự truyền tải dòng/dòng cấp dữ liệu sẽ được dịch sang nguồn cấp dữ liệu theo dòng trên đầu vào.
  • Nếu tệp được mở ở chế độ phụ thêm, phần cuối của tệp sẽ được kiểm tra một ký tự ctrl-z (ký tự 26) và ký tự đó bị loại bỏ, nếu có thể, nó cũng sẽ giải thích sự hiện diện của nhân vật đó như là phần cuối của tập tin Đây là một sự trì hoãn không may từ ngày CPM (một cái gì đó về tội lỗi của cha mẹ b eing đến thăm con cái của họ đến thế hệ thứ 3 hoặc thứ 4). Trái ngược với ý kiến ​​đã nêu trước đây, ký tự ctrl-z sẽ không được thêm vào.
+12

vận chuyển trở lại thực sự là '\ r', '\ n' là nguồn cấp dữ liệu dòng. –

+0

Liệu nó có hành vi này cho tất cả các loại hoạt động tập tin? Ví dụ. fread và fwrite (được sử dụng chủ yếu với các tệp nhị phân)? – Calmarius

+0

Bản dịch được chỉ định khi xử lý tệp được mở và diễn ra ở mức thấp. Nó sẽ diễn ra bất kể các chức năng mà bạn sử dụng để đọc (hoặc viết) tập tin. –

26

Trong chế độ văn bản, một dòng mới "\ n" có thể được chuyển đổi sang một chiếc xe ngựa return + newline "\ r \ n"

Thông thường bạn sẽ muốn mở ở chế độ nhị phân. Cố gắng đọc bất kỳ dữ liệu nhị phân nào trong chế độ văn bản sẽ không hoạt động, nó sẽ bị hỏng. Bạn có thể đọc văn bản ok ở chế độ nhị phân mặc dù - nó sẽ không làm bản dịch tự động của "\ n" thành "\ r \ n".

Xem fopen

+2

Để đọc, bản dịch hoạt động ngược lại với những gì bạn mô tả - chuyển đổi "\ r \ n" thành "\ n". –

+2

Nó chỉ là Windows? –

+1

techtonik: Tất cả nền tảng sẽ cho phép bạn chỉ định chế độ văn bản , nhưng trên unix/linux nó không khác với chế độ nhị phân. Chỉ trên Windows, nó tạo ra sự khác biệt. (Và có thể một số nền tảng mơ hồ hơn - bạn phải kiểm tra tài liệu nền tảng của mình để chắc chắn có) – MrZebra

5

Thêm vào đó, khi bạn fopen một tập tin với "rt" đầu vào được chấm dứt trên một nhân vật Crtl-Z.

+2

Đúng - Tôi tạo các định dạng tệp riêng của mình bắt đầu bằng một cái gì đó như "my-file-type^Z" , sau đó nếu bạn "nhập"/"mèo" từ dòng lệnh, nó chỉ cung cấp cho bạn "số ma thuật" của tệp và dừng thay vì phun nhị phân đến thiết bị đầu cuối của bạn. – MrZebra

2

Chúng tôi đã có một vấn đề thú vị với việc mở tập tin trong chế độ văn bản mà các tập tin đã có một hỗn hợp của dòng kết thúc nhân vật:

1\n\r 
2\n\r 
3\n 
4\n\r 
5\n\r 

yêu cầu của chúng tôi là chúng ta có thể lưu trữ vị trí hiện tại của chúng tôi trong file (chúng tôi sử dụng fgetpos), đóng tệp và sau đó mở lại tệp và tìm đến vị trí đó (chúng tôi đã sử dụng fsetpos).

Tuy nhiên, trong đó tệp có hỗn hợp kết thúc dòng thì quá trình này không tìm được vị trí thực tế giống nhau. Trong trường hợp của chúng tôi (công cụ của chúng tôi phân tích cú pháp C++), chúng tôi đã đọc lại các phần của tệp mà chúng tôi đã thấy.

Đi với nhị phân - sau đó bạn có thể kiểm soát chính xác những gì được đọc và ghi từ tệp.

4

khác biệt nữa là khi sử dụng fseek

Nếu dòng được mở trong chế độ nhị phân, vị trí mới là chính xác bù đắp byte đo từ đầu của tập tin nếu nguồn gốc là SEEK_SET, từ tập tin hiện tại vị trí nếu nguồn gốc là SEEK_CUR và từ cuối tệp nếu nguồn gốc là SEEK_END.Một số luồng nhị phân có thể không hỗ trợ SEEK_END.

Nếu luồng đang mở ở chế độ văn bản, giá trị được hỗ trợ để bù trừ là 0 (hoạt động với bất kỳ nguồn gốc nào) và giá trị được trả về bởi lệnh gọi trước đó tới std :: ftell trên luồng được liên kết với cùng một tệp (chỉ hoạt động với nguồn gốc của SEEK_SET

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