Pliki binarne i pojedyncze bity

0

Witam.

Problem zacza sie z drzewem huffmana (kompresja te sprawy) - drzewo z czestoscia wystepowania liter bedzie robione dynamicznie i dolaczane do pliku w formie naglowka.

Wszystko sobie obmyslilem na karteczce na dlugo przed zabraniem sie za kodzenie - teraz przyszla praktyka i ... no wlasnie nie moge zapisywac po jednym bicie (ani odczytywac) z pliku. W sumie c++ nie ma zadnej zmiennej majaca dokladnie jeden bit (nawet bool).

Chcialem zrobic juz tablice charow i operowac na pojedynczych bitach (co juz nawet napisalem) ale i tak nie zapisze do pliku rowno 7bitow a zawsze wielokrotnosc 8.

Macie jakies porady praktyczne co mozna zrobic zeby zapisac do pliku binarnego dokladnie 7bitow - przeciez musi sie jakos dac w koncu pliki nie zawsze sa wielokrotnoscia 8 a ja nie ort! ze c++ tak rozpowszechniony jezyk nie moze sobie z tym poradzic (to pewnie niewiedza)

Prosze o pomoc.

0

No chyba sobie żarty robisz, zapisać 7 bitów do pliku :D
A nie możesz ośmiu, tyle, że ostatni zawsze ignorujesz

EDIT:

abc napisał(a)

Wszystko sobie obmyslilem na karteczce na dlugo przed zabraniem sie za kodzenie - teraz przyszla praktyka i ... no wlasnie nie moge zapisywac po jednym bicie (ani odczytywac) z pliku. W sumie c++ nie ma zadnej zmiennej majaca dokladnie jeden bit (nawet bool).

a znasz jakiś język który może

w dziale C masz artykuł o nazwie: Tablica bitowa, dorób sobie metodę do pobierania wskaźnika na tamta tablicę z klasy i zapisuje zawartość tablicy do pliku+musisz jeszcze przed zawartością bitów zapisać z ilu dokładnie bitów składa się tablica...

albo zapisuj do plików od razu tą klasę, jej tymczasowy stan, z pliku odczytasz jej stan i już(EDIT: tfffffuuu, co ja piszę, to jest dynamiczna tablica, stanu klasy nie zapiszesz, chyba że wskaźnik do tablicy xd)

0

Na szybko:

1 - robisz kilkubajtowy bufor
2 - na nim wykonujesz operacje np do pierwszego bajta wpisujesz 3 bity, potem 4 bity i jeszcze 6 bitów. 5 się nie zmieści, więc wrzucasz je do drugiego bajta.
3 - jak wyjdziesz poza 1 bajt przerzucasz go do pliku, a bufor przesuwasz o jeden bajt, tak żeby znowu mieć go od początku, zapamiętując jednocześnie od którego bitu należy dodawać.
4 - wracasz do 2 ...

I tak aż nie skończą się dane, wtedy uzupełniasz zerami ostatni bajt.

Edytka:
@up na tym to właśnie polega (kompresja dokładnie), że wszystkie bity się oszczędza, bo co mu da to, że wg drzewka rozkładu 'A' może zapisać na 2 bitach i wtedy oszczędza 75% miejsca jakie zajęłyby litery 'A' skoro i tak zapisze to potem na 8bit. O kant kuli z taką kompresją :P

0
abc napisał(a)

8 a ja nie wieze ze c++ tak rozpowszechniony jezyk nie moze sobie z tym poradzic (to pewnie niewiedza)

To uwierz. Nie da się we współcześnie stosowanych systemach plików zapisać danych o ilości bitów niepodzielnej przez 8 - zawsze (!) musisz zapisać całe bajty - po prostu ignorujesz na końcu bity dopełniające. Pomyśl - nawet nie możesz zdefiniować typu danych, który nie ma pełnej ilości bajtów.. Nawet tablica bitowa korzysta niejawnie z pełno-bajtowego typu.

Swoją drogą nawet nie jest tak, że plik zajmuje na dysku dowolną ilość bajtów, ale pełne jednostki alokacji - to ukrywa przed Tobą system operacyjny.

0

No dobra wiec mogę zrobić tablicę charów co mi da najwyżej przy zapiscie do pliku nadmiar 7 bitów.

Pytanie jak najlepiej rozpoznać, że te 7 bitów było mi nie potrzebne (a z drzewem huffmana mogą się pokrywać przecież i plik po dekompresji bedzie sie roznil :()
//EDITED - nawet jak beda zerami drzewo moze byc jednoelementowe gdzie wystepuje tylko litera A odpowiadajaca 0

Zapisywanie na poczatku ile bitow wykorzystuje? tylko int moze nie starczyć w końcu bywają duże pliki (chociaż wątpie żebym kompresował 4GB plik...) - jakieś propozycje?

0

Możesz na końcu postawić wartownika, 1 bajt, który przechowuje ilość nadmiarowych bitów. Na przykład.
Przy odczycie skaczesz najpierw na koniec pliku, żeby odczytać wartownika i jednocześnie wiedzieć ile bajtów jest użytecznych (rozmiar -1).

Wydaje mi się to dość wygodnym rozwiązaniem, bo raz, jaka by nie była długość pliku to i tak bajt na to starczy, dwa zapisujesz wszystko ciurkiem, co w przypadku zapisu rozmiaru na początku mogło by być mniej wygodne.

0

a o polach bitowych albo wyżej, np. vector<bool> to Waść słyszałeś? A może Bitset? STL trochę zabawek do manipulacji na poziomie bitów oferuje, zacznij od zapoznania się z tym. Wczytujesz blokowo, wrzucasz w kontener, manipulujesz, zapisujesz blokowo. Vector<bool> jest specjalizowany do bycia 'prawdziwą' tablicą pojedynczych bitów.

Macie jakies porady praktyczne co mozna zrobic zeby zapisac do pliku binarnego dokladnie 7bitow - przeciez musi sie jakos dac w koncu pliki nie zawsze sa wielokrotnoscia 8

pliki zawsze są wielokrotnością 8 bitów, najmniejsza logiczna jednostka alokacji w pamięci czy też na dysku to bajt... a ten jak chyba wiesz ma 8 bitów. Zawsze będziesz miał wielokrotność 8 bitów, ale co za problem zapisać ile bitów z ostatniego bajtu faktycznie wykorzystujesz?

Szczawik napisał(a)

nie możesz zdefiniować typu danych, który nie ma pełnej ilości bajtów.. Nawet tablica bitowa korzysta niejawnie z pełno-bajtowego typu.

Tutaj się nie zgodzę - vector<bool> jest tablicą bitów, używa wszystkich bitów każdego zaalokowanego bajtu. Pola bitowe zaś w strukturze pozwalają na określenie konkretnych fragmentów pamięci, w bitach.

0

@deus - zgadza się, pola bitowe odpowiadają konkretnym bitom w strukturze.. ale to nie oznacza przecież, że możesz mieć rekord o niedopełnionym do bajtów rozmiarze. Dlatego napisałem:

korzysta niejawnie z pełno-bajtowego typu

Niejawnie, bo odnosi się do konkretnego bitu w jakimś (w pełni zaalokowanym!) bajcie. Nie miałem na myśl tego, że zapisanie bita zżera cały bajt.

No ale nie spierajmy się, mówiąc o tym samym - wniosek jest jeden: nie da się mieć pliku o niedopełnionej do bajtów ilości bitów. Kropka.

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