Wczytywanie pliku do bufora
Ostatnio zmodyfikowano 2020-04-02 12:05
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: #include <iostream> #include <cstring>
using namespace std;
class ByteBuffer { char * bufor_znakowy; int rozmiar_bufora; public: ByteBuffer( std::size_t BUFFER_SIZE ) { 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() { std::cout << "destruktor" << std::endl; if( bufor_znakowy != NULL ) delete bufor_znakowy; } void Clear() { std::memset( bufor_znakowy, '0', sizeof( char ) * rozmiar_bufora ); } void Pokaz() { 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; }
|
|
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. |
|
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) |
|
pekfos |
» 2020-04-01 16:27:08 Kurs STC 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. |
|
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 ? |
|
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. |
|
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.
void ReadIntoBuffer() { if( fileStream.eof() ) { koniecPliku = 1; } if( !fileStream.eof() ) { string memblock( RozmiarPliku, ' ' ); <--pad ł w tym miejscu fileStream.seekg( 0, ios::beg ); fileStream.read( & memblock[ 0 ], RozmiarPliku ); wczytuje plik fileStream.close(); istringstream inputIN( memblock ); ł aduje zawarto ś ć pliku do strumienia input.swap( inputIN ); } }
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 |
|
« 1 » |