Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Wczytywanie pliku do bufora

Ostatnio zmodyfikowano 2020-04-02 12:05
Autor Wiadomość
idepozapalki
Temat założony przez niniejszego użytkownika
Wczytywanie pliku do bufora
» 2020-03-31 21:35:59
Dzień dobry,
Ćwiczę z klasami i chciałbym napisać program wczytujący i przetwarzające duże pliki.
Napisałem klasę bufora z tablicą do przechowywania przeczytanej porcji bajtów z pliku.

Mam dylemat czy robię to w dobry sposób. Trochę poczytałem i wyczytałem że najszybszym sposobem będzie wczytywanie pliku do tablicy, do vectora byłoby wolniej. Czy do stringu też byłoby wolniej?

Kolejnym krokiem będzie przetwarzanie bufora dalej. Chciałbym z niego wyciągać pojedyncze linie. getline() mi się nie sprawdziło, bo bufor to nie strumień . Czy napisać sobie funkcję w C robiącą to samo co getline ?

To moja klasa:

C/C++
#include <iostream>
#include <cstring> //do funkcji memset

using namespace std;

class ByteBuffer {
    char * bufor_znakowy;
    int rozmiar_bufora;
   
public:
    ByteBuffer( std::size_t BUFFER_SIZE ) { // konstruktor
        std::cout << "konstrutor" << std::endl;
        bufor_znakowy = new( std::nothrow ) char[ BUFFER_SIZE ];
        if( !bufor_znakowy )
             throw std::bad_alloc();
       
        std::memset( bufor_znakowy, '0', sizeof( char ) * BUFFER_SIZE );
        this->rozmiar_bufora = BUFFER_SIZE;
    }
   
    ~ByteBuffer() { // destruktor
        std::cout << "destruktor" << std::endl;
        if( bufor_znakowy != NULL )
             delete bufor_znakowy;
       
    }
   
    void Clear() { // Wpisuje w cały bufor zera
        std::memset( bufor_znakowy, '0', sizeof( char ) * rozmiar_bufora );
    }
   
    void Pokaz() { // Pokazuje zawartosc wszystkich komorek bufora
        for( int i = 0; i < rozmiar_bufora; i++ ) {
            std::cout << bufor_znakowy[ i ];
        }
    }
   
    void PokazRozmiarBufora() {
        std::cout << rozmiar_bufora << std::endl;
    }
};

int main()
{
    ByteBuffer * buf1 = new ByteBuffer( 50 );
    buf1->Pokaz();
    cout << "\n";
    buf1->PokazRozmiarBufora();
    return 0;
}
P-176582
pekfos
» 2020-03-31 22:16:35
Mam dylemat czy robię to w dobry sposób. Trochę poczytałem i wyczytałem że najszybszym sposobem będzie wczytywanie pliku do tablicy, do vectora byłoby wolniej. Czy do stringu też byłoby wolniej?
Różnica wydajności jest tylko wtedy, kiedy używasz kontenera źle - a więc nie używając resize()/reserve() gdy z góry wiesz ile potrzebujesz pamięci.

Kolejnym krokiem będzie przetwarzanie bufora dalej. Chciałbym z niego wyciągać pojedyncze linie. getline() mi się nie sprawdziło, bo bufor to nie strumień . Czy napisać sobie funkcję w C robiącą to samo co getline ?
A czemu chcesz mieć cały plik w pamięci?
chciałbym napisać program wczytujący i przetwarzające duże pliki.
Ja przez duży plik rozumiem rozmiar typu 100GB. Do pamięci nie wejdzie.
P-176583
idepozapalki
Temat założony przez niniejszego użytkownika
» 2020-03-31 22:58:16
Zamierzałem przetwarzać po 4096 bajtów. Te 50 jest tam wpisane do testów. Ten kod działa.

Właśnie nie chciałbym mieć całego pliku w pamięci.

Pliki będą do 1GB może odrobinkę większe.

Sugerujesz że użycie vectora będzie równie wydajne ?

Tak na marginesie jak używać cytatów? (w linku do zakładania tematów nie doszukałem się tego)
P-176585
pekfos
» 2020-04-01 16:27:08
» KursyKurs STC kurs Tu jest opis wszystkich znaczników.

Zamierzałem przetwarzać po 4096 bajtów.
Strumienie plikowe już są buforowane i 4kB to typowy rozmiar. Niczego nie zyskasz robiąc drugą warstwę tego samego.
P-176586
idepozapalki
Temat założony przez niniejszego użytkownika
» 2020-04-01 16:34:57
A użycie dwóch buforów i ich późniejsza podmiana ?
P-176587
pekfos
» 2020-04-01 16:36:22
W jakim celu? Samo w sobie nie brzmi sensownie. Możesz mieć przykładowo jeden wątek który tylko czyta z pliku i drugi który tylko dane przetwarza, a między nimi kolejka 4-kilobajtowych buforów. Wtedy to ma jakąś wartość, bo wykorzystujesz czas procesora, który normalnie 'marnowałby się' w oczekiwaniu na dysk.
Najlepiej zrób bez kombinowania. Wtedy możesz zbadać wydajność i rozwiązywać konkretne problemy. Teraz rozmawiamy o teorii, która być może w ogóle nie będzie się sprawdzać w Twoim konkretnym zastosowaniu.
P-176588
idepozapalki
Temat założony przez niniejszego użytkownika
» 2020-04-02 12:05:59
Może osobnymi wątkami w tym momencie się nie zajmujmy.
Staram się ćwiczyć z klasami i chciałem przy okazji nauki i ćwiczenia zrobić coś pożytecznego.
Pewnie to wszystko jest w bibliotece STL do której już zaglądałem, ale na tym etapie wolałbym zrobić kilka własnych błędów i coś się na nich nauczyć. Na gotowce będzie jeszcze czas.

------------------------------------------------------

Chciałbym wrócić do tego tematu.
Idąc za radą napisałem funkcję wczytującą cały plik do Ramu.

C/C++
//---------------------------------------------------------
//
// Funkcja wczytuje plik do bufora
//
//---------------------------------------------------------
void ReadIntoBuffer() {
    if( fileStream.eof() ) {
        koniecPliku = 1; // zmienna pokazujaca koniec pliku
    }
    if( !fileStream.eof() ) {
        string memblock( RozmiarPliku, ' ' ); <--pad ł w tym miejscu
        fileStream.seekg( 0, ios::beg ); // ustawiam się na początku pliku
        fileStream.read( & memblock[ 0 ], RozmiarPliku ); wczytuje plik
        fileStream.close();
        istringstream inputIN( memblock ); ł aduje zawarto ś ć pliku do strumienia
        input.swap( inputIN ); // podmieniam strumienie
    }
}

Wszystko działa sprawnie przy małych plikach, rzędu kilkudziesięciu kB
Zachęcony pozytywnymi efektami wrzuciłem plik 700MB i program padł.
Wolnego Ramu jest wystarczająco. Od debugera dowiedziałem się, że program nie jest w stanie zaalokować takiej ilości pamięci.
Próbowałem też użyć:

char* buffer = new char[RozmiarPliku];
ale efekt ten sam.
RozmiarPliku = 708435628 bajtów

P-176597
« 1 »
  Strona 1 z 1