2010-11-11 9 views
6

Dla dobra nauki C i zrozumienie różnicy między pliki binarne i pliki tekstowe, jestem próby zapisu ciąg do pliku jako obu typów plików tak:Dlaczego fwrite() nie pisze pliku binarnego za pomocą "wb", w C, na Mac OS X?

char * string = "I am a string!"; 

FILE * filePtrA = fopen("/output.txt", "wt"); 
fwrite(string, strlen(string), 1, filePtrA); 

FILE * filePtrB = fopen("/output.bin", "wb"); 
fwrite(string, strlen(string), 1, filePtrB); 

fclose(filePtrA); 
fclose(filePtrB); 

Jednak są pisanie zarówno "wt" i "wb" jako plik tekstowy, gdzie "wb" powinien zapisywać jako plik binarny. Hex wygląda tak dla obu plików:

49 20 61 6D 20 61 20 73 74 72 69 6E 67 21 

Dlaczego tak się dzieje i jak mogę napisać coś jako plik binarny?

Przeczytałem, że system operacyjny (Mac OS X 10.6 - GCC 4.2) może nie rozróżniać plików binarnych i tekstowych, chociaż nadal jestem zakwestionowany, dlaczego edytor heksadecymalny nie wykryłby żadnej różnicy.

+0

Zastanawiam się, czego oczekuje się w pliku "binarnym"? – Vovanium

Odpowiedz

6

Wszystkie pliki są binarne.

Różnica między "plikami tekstowymi" a "plikami binarnymi" w kontekście fopen polega na tym, że standardowa biblioteka może wykorzystywać filtr do odczytywania i zapisywania pliku w trybie tekstowym. W trybie binarnym to, co piszesz, jest zawsze tym, co jest napisane.

Jedyny praktyczny przykład, jaki znam, to Windows, gdzie otwarcie pliku w trybie tekstowym spowoduje przekształcenie go między zakończeniami linii w stylu systemu Windows (CRLF, "\r\n") a zakończeniami linii w stylu C/Unix (LF , "\n"). Na przykład po otwarciu pliku do odczytu w systemie Windows w trybie tekstowym, zakończenia linii pojawią się w twoim programie jako "\n". Jeśli miałbyś otworzyć go w trybie binarnym, zakończenia linii pojawią się w twoim programie jako "\r\n".


Można również sprawdzić plik z cat, na przykład:

kot filename

należy uzyskać dane wyjściowe: I am a string!

+0

Poprawna składnia to "cat filename". – Darron

+1

Aby wyjaśnić; Nawiasy kątowe wokół "nazwy pliku" miały na celu jedynie zilustrowanie, że jest to zmienna, a nie coś, co można skopiować dosłownie. Więc zastąp ciąg '' przez rzeczywistą nazwę pliku i powinieneś być dobry :) –

+4

Wersje Mac OS przed OS X użyły '\ r' do oznaczenia końca linii, więc rozróżnienie trybu tekstowego/binarnego było tam też istotne. – caf

1

Jedyny tryb tekstu różnicowego powoduje, że kończy się wierszem. Tak więc, jeśli fprintf a \n zostanie przetłumaczone zgodnie z platformy. Dla przykładu, tryb binarny lub tekstowy nie ma znaczenia dla tego, co jest zapisane w pliku.

3

Oba pliki to pliki binarne. Są dokładną kopią danych wysłanych do fwrite. Niektóre uszkodzone systemy operacyjne mają pliki tekstowe, które nie są binarne; mają dodatkowe śmieci takie jak \r\n zastępujące \n, lub stałe rekordy linii itp. POSIX zabrania tego wszystkiego. W każdym systemie operacyjnym POSIX tryb tekstowy i binarny są identyczne.

Nawiasem mówiąc, "wt" nie jest prawidłowym argumentem trybu dla fopen. Tryb tekstowy jest domyślny. Modyfikator t, aby zażądać trybu tekstowego, jest rozszerzeniem uszkodzonych implementacji systemu Windows, w których wartością binarną jest wartość domyślna, ale tryb tekstowy jest dostępny na żądanie.

+0

Jakie implementacje mają binarny tryb domyślny? Moje doświadczenie zawsze było domyślnym trybem tekstowym (a w MS C modyfikator 't' jest zbędny, ale ludzie używają go dla jasności) –

+0

@ M.M: Tryb tekstowy jest zawsze trybem domyślnym; jest to wymagane przez ISO C. POSIX wymaga, aby tryb tekstowy i tryb binarny były identyczne, więc nie ma to znaczenia. –

1

Na większości Unix- jak systemy, jest nie różnica między otwieraniem pliku w tekście a trybem binarnym.Ponadto dane, które opisujesz powyżej, nie będą wykazywały różnicy nawet w wielu systemach, w których różne pliki traktowane są "tekstowo" i "binarnie".

Na przykład, podczas otwierania Windows plik w trybie tekstowym zwykle oznacza, że ​​"\ n", który napiszesz, zostanie przetłumaczone na "\ r \ n" w rzeczywistym pliku (i podczas czytania odwrotnie) . Ponieważ nie napisałeś "\ n", to tłumaczenie nie byłoby możliwe.

+0

Zastąp "większość" przez "wszystkie". POSIX wymaga identycznego trybu tekstowego i trybu binarnego. Jest to tak fundamentalne, że nie wydaje mi się, aby można było rozważyć dowolny system operacyjny, który nie jest "podobny do systemu Unix". –

1

Masz rację. Nie ma to znaczenia w systemach typu Unix. Discussion from the cygwin camp. Jaką różnicę spodziewałeś się zobaczyć? Piszemy tekst ASCII do pliku, a nie arbitralne dane binarne.

0

Unix jak OS traktuje oba tak samo. Nie jestem pewien, czy to jest właściwa odpowiedź, ale jeśli chcesz umieścić tekst jako szesnastkowy w pliku, spróbuj zastosować \ x przed text.e.g. jeśli próbujesz napisać powitanie do pliku, będziesz bufor:
char * buf = "hello";
Jeśli chcesz zapisać w pliku heks z "witaj", Twój bufor powinien być taki:
char * buff = "\ x68 \ x65 \ x6c \ x6c \ x6f";
Mam nadzieję, że pomogło

+0

W pamięci oba "buff" są dokładnie takie same. Nie ma różnicy. – Zulan

+0

Tak, ale różnica polega na zapisaniu pliku w pliku. W pierwszym przypadku "witaj", zostanie zapisane jako tekst w pliku, a "\ x68 \ x65 \ x6c \ x6c \ x6c \ x6f" zostanie zapisane jako plik w formacie heksadecymalnym, a nie w tekście – fluffybunny

+0

To źle. Ponieważ nie ma różnicy w pamięci, 'fwrite' po prostu zapisuje identyczny blok danych do pliku. Musisz używać '\ x' tylko dla znaków, które nie mogą być bezpośrednio zakodowane w pliku źródłowym. Po prostu spróbuj. – Zulan