Zapis do pliku binarnego .bin

0

Witam, muszę zapisać plik zero jedynkowy do pliku tak aby zajmował mniej niż gdybym zera i jedynki zapisywał w stringu. Tzn. obecnie mam tak że mam string "010101010101010" i zapisuję go do pliku. Ja chcę natomiast żeby to były bity a nie string (wtedy plik ponoć mniej zajmuje). Widziałem parę implementacji w internecie ale jak na moje potrzeby były zbyt skomplikowane a ja chciałbym takie coś napisać sam. Tu moje pytanie, czy wystarczy zrobić coś takiego że tworzę zmienną typu byte (0 lub 1) i bit po bicie zapisuję do pliku? To zadziała? Jeśli nie tak to się robi to jak? Pozdrawiam

0

Pewny nie jestem, ale w języku C++ to:

  1. możesz utworzyć tablicę typu bool i taką tablicę zapisać binarnie

  2. tutaj musiałbym sobie przypomnieć, ale zdaje się, że możesz zrobić strukturę, w której będziesz mógł utworzyć np. zmienną typu int i rozbić ją na bity -> wówczas mógłbyś upchnąć taki ciąg jeszcze bardziej skompresowany

ale niech może ktoś bardziej doświadczony się wypowie :)

0

Do pliku można pisać TYLKO całymi bajtami. Musisz sobie stworzyć tablicę bajtów i ją zapisać do pliku.

0

jeśli na zapisanie bitu będziesz używać całego bajta, to zabawa mija się z celem, bo tracisz 7/8 miejsca. zapoznaj się z operacjami logicznymi na bitach i bajtach - and, or, shift left/right.
pseudokod:

bool getBit(byte[] table, int bitIndex) {
    byte tableIndex = bitIndex / 8;
    bitIndex = bitIndex % 8;
    byte byteFromTable = table[tableIndex];
    
    return (byteFromTable >> tableIndex & 1) == 1;
}

setBit(byte[] table, int bitIndex, bool value) {
    byte tableIndex = bitIndex / 8;
    bitIndex = bitIndex % 8;
    byte byteFromTable = table[tableIndex];
    
    if (value)
        table[tableIndex] = byteFromTable | 1 << bitIndex
    else
        table[tableIndex] = byteFromTable & !(1 << bitIndex);
}

brakuje sprawdzenia, czy indeks nie wychodzi poza tablicę, poza tym całość napisana z palca, ale chyba wiadomo mniej-więcej o co chodzi?

0

Nie bardzo to rozumiem pod względem teoretycznym. Mógłby ktoś to wyjaśnić? Wydawało mi się zawsze że skoro mamy w pliku jakiś tekst, to jeden znak zajmuje jakąś stałą liczbę bajtów. Czyli metoda

if(znak=='0') { byte znak = 0; }
else { byte znak = 1; }
write(znak); 

nie zadziała?

0

Zadziała, ale ona pod względem wymagań z zadania nic nie zmienia. Najczęściej jeden znak odpowiada jednemu bajtowi, więc na niczym nie zaoszczędzisz.

Ponawiam pytanie: jaki język programowania?

0
MateuszS napisał(a):

Nie bardzo to rozumiem pod względem teoretycznym. Mógłby ktoś to wyjaśnić? Wydawało mi się zawsze że skoro mamy w pliku jakiś tekst, to jeden znak zajmuje jakąś stałą liczbę bajtów. Czyli metoda

if(znak=='0') { byte znak = 0; }
else { byte znak = 1; }
write(znak); 

nie zadziała?

jeden znak to zwykle jeden bajt, sporadycznie dwa (UTF-8, UTF-16). jeśli zapisujesz do pliku bajt o wartości 1, no to wybacz, w pliku ląduje bajt o wartości 1, czyli siedem bitów 0 i bit 1. przeanalizuj to, co napisałem w poprzednim poście - musisz wykorzystać każdy bit w bajcie i dopiero takie bajty zapisywać. poza tym Twoje pytania to programistyczny żłobek, poszukaj dobrego tutoriala w internecie i z jego pomocą załap o co chodzi, bo inaczej nie będziesz rozumieć naszych odpowiedzi.

0

Ok, nie oddałem projektu w 1 terminie i trochę poczytałem o operatorach bitowych itp. Niestety mimo że wiem co robią poszczególne opratory, ŁF nie bardzo zrozumiałem co zrobiłeś w kodzie, który wysłałeś, za duży skrót myślowy (sam kod zrozumiałem ale nie wiem jak to ma mi pomóc w konwersji). Skoro np. na znak przypada mi bajt = 8 bitów, to muszę zrobić coś takiego że przesuwam jedynki w lewo o ileś bitów a w zerach, które mi się pojawiają po "prawej" mam upchnąć kolejny znak bitowo?

0

prawie. chcesz np. ustawić czwarty bit licząc od zera. więc 1 przesuwasz o cztery miejsca w lewo (1 << 4) a potem przypisujesz to do odpowiedniego bajta. ponieważ nie chcesz zmienić pozostałych bitów tego bajta, to robisz operację OR, czyli Twój bajt xxxnxxxx = xxxnxxxx | (1 << 4) => xxx1xxxx i bit ustawiony. jeśli chcesz ten sam bit zgasić, to robisz ciut inaczej, przez NOT i AND: 1 << 4 => 00010000, !(1 << 4) => !00010000 => 11101111, Twój bajt xxxnxxxx = xxxnxxxx & !(1 << 4) => xxxnxxxx & 11101111 => xxx0xxxx.
jeśli chcesz pobrać dziesiąty bit licząc od zera, to najpierw obliczasz offset bajta, czyli indexTablicy = offset / 8, pobierasz tego bajta, a potem przesuwasz wszystko w lewo o offset % 8 i pobierasz najmłodszy bit. tutaj offset % 8 = 2, więc drugi bit licząc od zera, więc zwracasz xxxxxnxx >> 2 & 1 => 00xxxxxn & 1 => n.

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