Optymalny zapis "dwójkowej" liczby, przechowywanej w stringu, do pliku binarnego.

0

Witajcie, mam w stringu liczbę binarną, którą chcę przechować w pliku. Zapisanie jej jako tekst składający się tylko z zer i jedynek jest bardzo nieoptymalne. Mniej zajmuje gdy przekonwertuję ją na system dziesiętny i taką liczbę zapiszę jako tekst. Mimo wszystko, np. plik z liczbą "974" zapisaną jako tekst, zajmuje 3 bajty, a jeśli dobrze rozumuję "1111001110" nie powinno zająć więcej niż 2. A gdy w/w liczbę zapiszę jako binarkę, zgodnie ze sposobem podanym w tym artykule - Odczyt i zapis plików binarnych w Cpp czyli w taki sposób:

file.write( reinterpret_cast <const char*> (&number_974), sizeof( number_974 ) );

wówczas wygenerowany plik zajmuje aż 4 bajty. Głowię się i głowię, jak tę liczbę zapisać do pliku żeby ów plik miał jak najmniejszy rozmiar.

1

wówczas wygenerowany plik zajmuje aż 4 bajty.

sizeof( number_974 )
Raczej rzutuj na short int (int16_t/uint16_t), skoro chcesz, aby były dwa bajty.

0

A czego się niby spodziewasz? Jak number_974 jest intem to zajmuje 4 bajty. Jak zrobisz z niej shorta to będą 2. Zauważ że jakbyś na pałę pisał do pliku tylko tyle zer/jedynek ile potrzeba do zapisu danej liczby to potem nie wiedziałbyś jak to odczytywać. Bo jak masz w pliku
1010101
to ile to jest takich liczb zapisanych tak jak byś to chciał zrobić? Jedna? Dwie? Trzy? ;] Dlatego zapisuje się je zawsze na takiej samej liczbie bitów, nawet jeśli zapisujesz 1 i będziesz tam miał 31 zer...

1

To żeby ten temat niósł pożytek dla przyszłych czytających, opiszę jak udało mi się to rozwiązać : wejściowy ciąg zer i jedynek przechowywany w stringu, uzupełniam zerami na początku(jeśli jego długość jest różna od liczby podzielnej przez 8), następnie pobieram (i usuwam) z niego po 8 początkowych cyfr, konwertuję te 8 cyfr(zer/jedynek) na system dziesiętny (do zmiennej int), mając w ten sposób liczbę z przedziału < 0, 255 >, odejmuję od niej 128 (ponieważ metoda "write" z ofstream'a przyjmuje tylko char, a nie unsigned char) otrzymując liczbę z przedziału < -128, 127 > (czyli najczęściej spotykany zakres chara) i tę liczbę rzutowaną zapisuję do pliku binarnego napisaną w pierwszym poście metodą. Powtarzam aż się skończą znaki w stringu (za każdym razem pobierając i usuwając po 8 początkowych znaków, pamiętając że liczba znaków w stringu jest podzielna przez 8). Dzięki temu otrzymuję plik binarny o rozmiarze identycznym liczbie bitów początkowej liczbie binarnej (czyli plik zajmuje tyle bitów ile znaków miał string w którym przechowywana była liczba) tylko zaokrąglonej (w górę) do pełnych bajtów (więc nadpisuję maksymalnie 7bitów). O taką optymalność mi chodziło :)

Co prawda temat pyta tylko o zapis, ale od razu opiszę pokrótce też odczyt: funkcją zapisującą zwracam sobie liczbę zapisanych znaków (charów) a żeby odczytać korzystam z ifstreamowej metody "read" podając jako drugi parametr właśnie tę liczbę, i przypisuję je do dynamicznie alokowanej (operatorem new) tablicy charów o takim właśnie rozmiarze. Po pobraniu przelatuję forem całą tablicę, odczytując wartość(int) danego chara, dodając do niego 128 (sytuacja odwrotna do tej przy zapisie) i konwertuję na system dwójkowy. Do tak przekonwertowanej liczby dodaję na początku zera(jeśli składa się z mniej niż 8 zer/jedynek) żeby nie stracić zer które przecież są fragmentem pierwotnej liczby binarnej. Nie robię tego jedynie przy pierwszym odczycie, bo zera z przodu nie wpływają na wartość. Te odczyty doklejam do stringa i w ten sposób odtwarzam liczbę identyczną do tej z przed zapisu do pliku.

Może komuś się przyda, w każdym razie powyższy opis to dokładnie to czego szukałem zakładając ten temat, cieszę się że udało mi się rozwiązać :)

0

odejmuję od niej 128 (ponieważ metoda "write" z ofstream'a przyjmuje tylko char, a nie unsigned char) otrzymując liczbę z przedziału < -128, 127 >

O rzutowaniu słyszał?
http://ideone.com/mpWvTM

0

No ale rzutując bierze wartości od dolnego przedziału (np. 128 na -128, 129 na -127, 130 na -126 itd) to wygodniej mi było odjąć, żeby potem tylko dodać. No ale to przecież bez znaczenia, a w gruncie rzeczy w pewnym sensie to to samo :P Znaczenie ma raczej pozostała część, w każdym razie ja już pytań więcej nie mam, więc jeśli o mnie chodzi to temat można zamknąć :)

0

A w jaki sposób zapisujesz długość tej liczby w pliku. Do pliku zapisuje się np. po to, żeby potem odczytać przy następnym uruchomieniu programu. Co będzie jak np. zapiszesz 3 liczby w pliku - skąd będziesz wiedział które bajty należą do danej liczby, a które nie?

1 użytkowników online, w tym zalogowanych: 0, gości: 1