2015-09-01 50 views
7

Próbuję napisać plik zakodowany w UTF-16 używając std :: ofstream(). Nawet w trybie binarnym zapisywanie "\n\0" jest zapisywane jako "\r\n\0". Przykładowy kod:std :: ofstream pisze r nawet w trybie binarnym

std::string filename = ... 
std::ofstream fout(filename, std::ios_base::binary); 
fout.write("\xff\xfe", 2); 
fout.write("\n\0", 2); 
fout.close(); 

dane hex plik wynikowy jest:

ff fe 0d 0a 00 

muszę robić coś złego. Jakieś pomysły, aby zapobiec pisaniu 0x0d?

Używam MS VisualStudio 2013

Update: To niewytłumaczalny rozpoczął pracę zgodnie z oczekiwaniami. Pisz po duchach w maszynie.

+0

W trybie binarnym nie powinno być tłumaczenia . Jeśli istnieje tłumaczenie, jest gdzieś błąd. –

+1

Co z 'fout.write (" \ x0a \ 0 ", 2);'? –

+0

To by działało, ale PO działa w niewłaściwy sposób. Ta ścieżka doprowadzi jedynie do większego bólu i nędzy oraz gróźb Unicode. –

Odpowiedz

-4

Zgodnie z projektem. Znak \ n jest konwertowany na znacznik EOL dla twojej platformy, więc funkcja output :: write poprawnie je interpretuje. Jeśli chcesz zapisać plik binarny, nie możesz używać specjalnych znaków tekstowych.

Wyjaśnienie: Udało mi się wprowadzić trochę zamieszania w to, co robi kompilator. Zasadniczo \ n jest specjalną postacią, która oznacza "EOL/End of Line" Jest to różne w zależności od platformy, na której się kompilujesz.

Teraz funkcja write() pobiera tablicę bajtów do zapisu w strumieniu. Standard C nie rozróżnia między ciągiem znaków (technicznie nie ma czegoś takiego w C) a tablicą znaków (lub bajtów), więc pozwala ci to uciec. Co się dzieje podczas kompilacji jest to, że te linie są coraz przekształcić w coś takiego:

fout.write({255, 254, 0}, 2); // "\xff\xfe" 
fout.write({13, 10, 0, 0}, 2); // "\n\0" 
fout.close(); 
+0

Czy przekazanie '\ x0A' (znak podawania wiersza) działa? Myślę, że tylko '\ n' ma specjalne znaczenie, ale nie jestem pewien. – SirGuy

+0

Prawdopodobnie?Jeśli chcesz pisać pliki UTF-16, naprawdę powinieneś używać do tego odpowiednich funkcji bibliotecznych (zwykle funkcji wc), a nie próbować kodować ręcznie UTF. Standard jest na tyle skomplikowany, że prawdopodobnie nie zrobisz tego dobrze. –

+1

Nowe tłumaczenie linii na CR + LF dzieje się w środowisku wykonawczym, a nie w kompilatorze. I powinno się to robić w trybie tekstowym, a nie binarnym. Użycie 'fout.write (" \ x0a ", 1)' ma taki sam efekt. – Jason

1

Wysłałeś 4 bajty na wyjściu. 5 zaobserwowano na wyjściu.

W pewien sposób nie korzystałeś z trybu binarnego. Nie ma innego sposobu użycia .write (buf, 2) i .write (buf, 2) i uzyskanie 5 bajtów wyjściowych.

Prawdopodobnie w trakcie rozgrywania/zabawy z rzeczami (jak zawsze ludzie robią, próbując dowiedzieć się, dlaczego dziwne zachowanie), coś, co zmieniliście, spowodowało, że faktycznie działa tryb binarny.

Jeśli wcześniej próbowałeś wyprowadzać na STDOUT lub STDERR, jest całkiem możliwe, że Windows automatycznie dodawał '\ r' do strumienia, ponieważ STDOUT i STDERR są prawie zawsze tekstem, a to mogło być nadpisaniem twojej próby umieścić go w trybie binarnym. (Nie, naprawdę, nie, używasz Visual Studio, to jest naprawdę. Tak, jeśli używasz cygwin, to nie jest prawda, ale używasz VS.)