Procvič si angličtinu zdarma s naším americkým e-learningem! Learn more
Pouze tento týden sleva až 80 % na celý Java e-learning!
Avatar
Matěj Strnad:8. srpna 18:47

Ahoj,

potřebuji číst a zapisovat v bity z/do souboru, jak to mám udělat jednoduše a efektivně? S bity potřebuji pracovat v datovém typu std::string, soubory mohou mít i desítky MB.

Děkuji za odpověď :)

Zkusil jsem: Googlit, něco jsem našel ale moudrý z toho nejsem :)

Chci docílit: Čtení/zápis bitů z/do souboru v C++

 
Odpovědět 8. srpna 18:47
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Matěj Strnad
ostrozan:10. srpna 16:16

A už jsi slyšel o tom, že soubor je vlastně jen dlóóóóuhá řada bitů nakrájená po osmi na bajty a kousek té řady se jmenuje hlavička, ve které je zapsáno, jak se ta řada má nasekat na kousky a co s těma kouskama udělat?
Takže jakýkoliv zápis /čtení splňuje tvé požadavky - pokud teda nebudeš konkrétnější.

 
Nahoru Odpovědět 10. srpna 16:16
Avatar
Odpovídá na ostrozan
Matěj Strnad:10. srpna 20:34

Potřebuji to rozdělit na jednotlivé bity, takže do stringu získat data souboru v 1 a 0 :)

 
Nahoru Odpovědět 10. srpna 20:34
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Matěj Strnad
ostrozan:10. srpna 22:23

Takže raw data souboru převést na textový soubor s nulama a jedničkama ?
K čemu je to dobré, kromě toho, že soubor bude osmkrát větší?

 
Nahoru Odpovědět 10. srpna 22:23
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Matěj Strnad
DarkCoder:10. srpna 22:51

Hodnoty 0 a 1 představující bitové hodnoty, které jsou uloženy v souboru, jsou stále brány jako znak. Takže způsob čtení nebo zápisu "klasického" znaku nebo znaku odpovídající 0 nebo 1, je úplně stejný. Spíše bych řekl že potřebuješ převádět klasický text do binární podoby a naopak, obsah souboru tvořený z 0 a 1 zpět na text.

Jádrem toho všeho je umět převést znak do binární podoby.

for (int i = CHAR_BIT - 1; i >= 0; i--) cout << ((c >> i) & 1);

Převod celého textu je už alternativa doplněná o traversing souboru nebo řetězce, podle toho odkud znaky vytahuješ.

Následující kód ukazuje výpis binární reprezentace řetězce na obrazovku.

unsigned char text[] = "www.itnetwork.cz", *ptext = text;
while (*ptext) {
        for (int i = CHAR_BIT - 1; i >= 0; i--) cout << ((*ptext >> i) & 1);
        ptext++;
}

Ve svém případě akorát provedeš změny v traversování souboru nikoli řetězce a zápisu do řetězce, nikoli na obrazovku.

Nahoru Odpovědět  +1 10. srpna 22:51
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Odpovídá na ostrozan
Erik Šťastný:11. srpna 9:24

Človek by se divil, kde se to takto používá. Například firma Lattice má soubory firmwarů opravdu zapsané 0 a 1 textově :D

 
Nahoru Odpovědět 11. srpna 9:24
Avatar
Caster
Člen
Avatar
Caster:12. srpna 7:05

Proč nějaké konverze ? Alokuj si potřebný prostor v paměti a pak ho celý čti/zapiš do souboru. Velikost souboru "desítky MB" nejsou žádný problém. Sám pracuji s textovým souborem 4 GB, který načtu najednou do paměti a pak s ním pracuji.

 
Nahoru Odpovědět 12. srpna 7:05
Avatar
Peter Mlich
Člen
Avatar
Odpovídá na Caster
Peter Mlich:12. srpna 9:32

Pokud s tim souborem moc casto nepracujes (vetsinu casu slouzi pro cteni), tak jej muzes na disku zabalit do zipu. Zipovani je dnes pomerne rychla zalezitost.

 
Nahoru Odpovědět 12. srpna 9:32
Avatar
Caster
Člen
Avatar
Odpovídá na Peter Mlich
Caster:12. srpna 9:56

Načtení souboru 4 GB trvá cca 2,5 sekundy, zipování není potřeba. S daty (38 mil. řádků/GPS souřadnic) pak pracuji v RAM. Program v C++ volá funkce v ASM 64bit. Zpětné hledání trasy mořských bójí (cca 23 000) v Indickém oceánu z 12ti míst v cyklu (80 až 108 E, 0 až 40 S po 1°) je otázkou několika sekund včetně vynesení jejich tras na mapě. Data jsem si předem setřídil, převedl na integer hodnoty a hledám je půlením intervalu.

 
Nahoru Odpovědět 12. srpna 9:56
Avatar
Peter Mlich
Člen
Avatar
Odpovídá na Caster
Peter Mlich:12. srpna 12:17

Ok.
Jen jsem chtel rici, ze, pokud ten soubor mas na disku, tak by mohlo byt efektivni pouzit zip i za cenu o 10% pomalejsiho nacteni.
Pro to, co popisujes, bych pouzil databazi a sql prikazy (casy v milisekundach). Import do db ale chvili trva u 4GB.

 
Nahoru Odpovědět 12. srpna 12:17
Avatar
Caster
Člen
Avatar
Odpovídá na Peter Mlich
Caster:13. srpna 20:28

Jak na čtení velkých souborů a alokaci paměti prakticky, část z mého programu:

const wchar_t *fname = L"C:\\Users\\Jan\\Soubor.txt";
__int64 delka = 0;
__int64 nacteno = 0;
const DWORD cti_blok = 2501566399;
BYTE* ptr = NULL;
BYTE* bsrc = NULL;
unsigned __int64 adresa = 0;
int radku = 0;
...
delka = FileSize(fname); // 64 bitů

        //* Zkusíme otevřít soubor pro čtení *//
        HANDLE handle = CreateFile(fname, GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
        //if (handle == INVALID_HANDLE_VALUE)
        //      report_error("Unable to open input file!\n");


        //* Alokujeme pamět pro celý soubor *//
        static const SIZE_T giga = 1024 * 1024 * 1024;
        static const SIZE_T size = 5 * giga;
        ptr = static_cast<BYTE*>(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
        bsrc = ptr;

        //* Načteme soubor *//
        DWORD bytes_read;
        cti_znaku = cti_blok;
        do {
                BOOL e = ReadFile(handle, ptr, cti_znaku, &bytes_read, nullptr);
                nacteno += bytes_read;
                ptr += bytes_read;
                if (delka - nacteno < cti_blok) {
                        cti_znaku = delka - nacteno;
                }
        } while (nacteno < delka);
        CloseHandle(handle);

        // Upravíme načtená data v poli
        adresa = (unsigned __int64)bsrc;
        radku = nacteno / 125;                                  // Pro úpravu dat v C++
        __int64 result = Funkce_Uprav(adresa);
        ...
_int64 FileSize(const wchar_t* name)
{
        WIN32_FILE_ATTRIBUTE_DATA fad;
        if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
                return -1; // error condition, could call GetLastError to find out more
        LARGE_INTEGER size;
        size.HighPart = fad.nFileSizeHigh;
        size.LowPart = fad.nFileSizeLow;
        return size.QuadPart;
}
 
Nahoru Odpovědět 13. srpna 20:28
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 11 zpráv z 11.