[c++] zapis binarny do pliku , problem

0

Hej,

załózmy ze mam np. takie dwa znaki (jeden i zero) 10 i chcialbym ja binarnie zapisac do pliku (tak by w pliku binarnym bylo 10 - czyli tylko d bity), jak to zrobic ?

moje przemyslenia:

ostream FILE - ma juz otwarty plik

char tab[3];
for (int i=2; i>=0; i--)
{
if (tab[i] & 1)
FILE.write(i co tu) //to musze zapisac jedynke

  FILE.write(i co tu)  // to musze zapisac 0

}

z gory dzieki

0

po prostu wpisujesz do pliku znak "1" i znak "0". Nie rozumiem ocb.

Jeśli chodzi Ci o binarny zapis pliku, to musisz go otworzyć z odpowiednimi parametrami, a wpisujesz tak jak w zwykłym pliku.

0

tylko przy takim zapisie plik binarny nie ma 2 bitow, a az 8 bajtow, ja chce zapisac to tak, aby ten plik byl najmniejszy

0

Pokaż kod.

0

chociazby (zapisuje samą jedynke):

FILE.open("plik.dat", std::binary);
char a[1];
a[0]=1;
FILE.write(a, 1);

plik bedzie mial 1 bajt, a mi zalezy na tym by mial tylko 1 bit...

0

Wydaje mi się, że w ten sposób tego nie zrobisz. Program przy otwarciu, w jakiś sposób znaki musi reprezentować.

0

no wlasnie to nie dziala, tylko kompletnie nie wiem jak zrobic to by zapisac to tak "bitowo", a jest mi to niezbedne w projekcie ktory chcialem sobie napisac...

0

Plik zawsze, ale to zawsze będzie miał co najmniej 1 bajt z powodu ograniczeń systemów plików oraz bezsensowności takiego zapisu. Po prostu się nie da, bo w C/C++ i każdym innym języku programowania (chyba nawet w assemblerze) do pliku można zapisać co najmniej 1 bajt.

0

ok, rozumiem, ze musi byc minimum jeden bajt, czy wiecej dopelnione do calego bajta...

ale mi chodzi o to ze chce zapisac np. taka wiazanke do pliku 0101010100000000010101010101010010101001010101... (i tych zero i jedynek moze byc np. milion) i tu jezeli zapisze to tak "bitowo" zauwaza znaczaco oszczednosc miejsca...
Jak cos takiego zrealizowac ?

0

& - bit and
| - bit or
To powinno wystarczyć.

0

teraz mnie rozwaliles normalnie :)

nie orientuje sie, w jaki sposob dokladniej te operacje bitowe moga byc potrzebne w moim zadaniu ?

0

W trybie binarnym do pliku zapisujesz bajty, nie ma możliwości "wysłania" do pliku pojedynczego bitu, żeby był on ładnie w tym pliku spakowany. Najmniejszą porcją danych jest bajt i musisz przed zapisem wypełnić go odpowiednią kombinacją bitów. Jeżeli chcesz zapisać ciąg bitów np. 01010110 to jest to 0x56 i taki bajt zapisujesz do pliku.
Jeżeli chciałbyś zapisywać "bit po bicie" to de facto zapisałbyś pojedyncze bajty niosące tylko jeden bit informacji.

0
unsigned char bajt0, bajt1, bajt2, bajt3, bajtW1, bajtW2;
bajt0 = 0; //00000000
bajt1 = 1; //00000001
bajt2 = 2; //00000010
bajt3 = 4; //00000100
//itd.
//teraz np.
bajtW1 = bajt1 | bajt4; //00000101
bajtW2 = bajtW & bajt2; //00000000 - drugi bit w bajt W1 nie jest ustawiony

Nie wiem czy się da to prościej przedstawić

0

ciąg bitów np. 01010110 to jest to 0x56

Mógłbyś mi powiedzieć jak to policzyłeś? Pytam, bo nie wiem i jestem bardzo ciekawy.

0
Blood napisał(a)

ciąg bitów np. 01010110 to jest to 0x56

Mógłbyś mi powiedzieć jak to policzyłeś? Pytam, bo nie wiem i jestem bardzo ciekawy.

Chociażby kalkulatorem windowsowym :p 0x56 to jest liczba w systemie szesnastkowym

0
Blood napisał(a)

ciąg bitów np. 01010110 to jest to 0x56

Mógłbyś mi powiedzieć jak to policzyłeś? Pytam, bo nie wiem i jestem bardzo ciekawy.

Ciąg bitów: 0101 0110
0101 (binarnie) = 5(heksadecymalnie) = 08+14+02+11
0110 (binarnie) = 6(heksadecymalnie) = 08+14+12+01

0

tylko ja w programie po ilus tam wczesniejszych operacjach otrzymuje bardzo duzego stringa o zawartosci 101011...00101 itp

wiec czy nie da sie moze zrobic jakiejs tablicy bajtow (mozliwa tablica charow ? (latwo wyuskac ze stringa - c_str())) i jakos go poprzerabiac operacjami, aby pozniej zapisac cala tablice, jesli tak to jak to mniej wiecej mialoby wygladac ?
z gory dzieki

0

aha okey, nie wiedziałem, że to heksadecymalny.

a mam jeszcze jedno pytanie - widziałem w niektórych programach, że na początku deklarowane są tablice właśnie z wieloma takimi bajtami zapisanymi w kodzie heksadecynalnym. Możecie mi powiedzieć po co się takie coś robi? Głównie to było w różnego rodzaju wormach i trojanach.

Jeśli do wytłumaczenia tego jest Wam potrzebny kod źródłowy - to przepraszam za głupie pytanie.

0

Na szybko(nie sprawdzałem czy działa):

string strBity;
unsigned char *cBajty;
unsigned int uIloscBajtow = strBity.length() / 8;  //ilosc w pełni zapełnionych bajtów
unsigned int nrBitu = 7, nrBajtu = 0;

if(strBity.length() % 8 > 0) uIloscBajtow++ //jeżeli ilość bitów nie jest dzielnikiem 8 to potrzeba jeszcze jeden bajt;
cBajty = new unsigned char [uIloscBajtow];
memset(cBajty, 0, uIloscBajtow); //wyzerowanie całej tablicy bajtów, żeby się pozbyć śmieci

for(int i = 0; i < strBity.length(); i++)
{
    if(strBity[i] == '1')
        cBajty[nrBajtu] |= pow(2, nrBitu); //ustawienie odpowiedniego bitu w aktualnym bajcie

    nrBitu++;           //reszta na potrzeby iteracji po tablicy bajtów
    if(nrBitu > 7)
    {
        nrBitu = 0;
        nrBajtu++;
    }
}

//tu zapisujesz wszystkie bajty z cBajty

delete [] cBajty;
0

dzieki, ale w miedzyczasie napisalem wlasny, jak ktos ma chwile to moglby rzucic okiem, bo nie wiem czy dziala ok, a na razie nie mam jak zdekodowac tego z powrotem:

unsigned a = 0;
    unsigned mas1 = 1;
    unsigned mas2 = 2;
    unsigned mas3 = 4;
    unsigned mas4 = 8;
    unsigned mas5 = 16;
    unsigned mas6 = 32;
    unsigned mas7 = 64;
    unsigned mas8 = 128;

    i = 0;
    
    int tab[8];
    for (int i = 0; i < 8; ++i)
        tab[i] = 0;
    int j = 0;
    while (calosc[i])
    {

        while (j < 8)
        {
            if (calosc[i] == '1')  //calosc to string z zerami i jedynkami
                tab[j] = 1;
            else
                tab[j] = 0;
            j++;
            i++;
        }

        if (j == 8)
        {

            if (tab[0] == 1)
                a |= mas8;
            if (tab[1] == 1)
                a |= mas7;
            if (tab[2] == 1)
                a |= mas6;
            if (tab[3] == 1)
                a |= mas5;
            if (tab[4] == 1)
                a |= mas4;
            if (tab[5] == 1)
                a |= mas3;
            if (tab[6] == 1)
                a |= mas2;
            if (tab[7] == 1)
                a |= mas1;
            j = 0;
            ++i;
        }

        FILE << a;  //czy taki sposob zapisu do pliku jest dobry ?


    }

    




    FILE.close(); 
0

wydaje sie ze ta wersja jest poprawna, ale czy na pewno ?
i jakie znaczenie ma zamiana w pierwszej lini unsigned char a = 0; na unsigned int a = 0; (pierwsza wersja kompresuje znacznie bardziej, ale czy ktorakolwiek robi to poprawnie ? :) )

unsigned char a = 0;
    unsigned mas1 = 1;
    unsigned mas2 = 2;
    unsigned mas3 = 4;
    unsigned mas4 = 8;
    unsigned mas5 = 16;
    unsigned mas6 = 32;
    unsigned mas7 = 64;
    unsigned mas8 = 128;

    i = 0;
    
    int tab[8];
    for (int i = 0; i < 8; ++i)
        tab[i] = 0;
    int j = 0;
    while (calosc[i])
    {

        while (j < 8)
        {
            if (calosc[i] == '1')  //calosc to string z zerami i jedynkami
                tab[j] = 1;
            else
                tab[j] = 0;
            j++;
            i++;
        }

        if (j == 8)
        {

            if (tab[0] == 1)
                a |= mas8;
            if (tab[1] == 1)
                a |= mas7;
            if (tab[2] == 1)
                a |= mas6;
            if (tab[3] == 1)
                a |= mas5;
            if (tab[4] == 1)
                a |= mas4;
            if (tab[5] == 1)
                a |= mas3;
            if (tab[6] == 1)
                a |= mas2;
            if (tab[7] == 1)
                a |= mas1;
            j = 0;
           // ++i;
        }

        FILE << a;  //czy taki sposob zapisu do pliku jest dobry ?
        a=0;


    } 
0

char i unsigned char ma rozmiar jednego bajtu, int ma rozmiar 32 bitów - 4 bajty

Wygląda ok, poza tym, że jest dużo niepotrzebnego kodu

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