11.07.2015 Views

przetwarzanie blokowe

przetwarzanie blokowe

przetwarzanie blokowe

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hPrzetwarzanie plików binarnych, koncepcjaAby korzystać z <strong>blokowe</strong>go odczytu i zapisu musimy spełnić dwa warunki:musimy dysponować otwartym plikiem, zaleca się, aby plik taki otwarty byłw trybie binarnym;musimy w programie posiadać zmienną — która realizuje funkcję bufora —z której będą pobierane dane do zapisu, lub do której będą pobierane danew przypadku odczytu.ProgramZmienna buforowaOdczyt blokufreadZapis blokufwriteCopyright © Roman Simiński Strona : 3


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hPrzetwarzanie plików binarnych, przykładZałóżmy, że chcemy napisać program, którego zadaniem jest:utworzenie nowego pliku binarnego, zapisanie do niego liczby typu floato wartości 123.321, zamknięcie pliku;powtórne jego otwarcie w trybie do odczytu, odczytanie zapisanej wcześniejliczby i wyprowadzenie jej do stdout.Copyright © Roman Simiński Strona : 4


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hPrzetwarzanie plików binarnych, otwarcie pliku, zapis liczby typu float#include #include int main(){FILE * fp;float num = 123.321;if( ( fp = fopen( "d.dat", "wb" ) ) != NULL ){printf( "\nZapis liczby: %g", num );fwrite( &num, sizeof( num ), 1, fp );fclose( fp );}...}return EXIT_SUCCESS;Copyright © Roman Simiński Strona : 5


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hPrzetwarzanie plików binarnych, zapis zmiennej numRozmiar zapisywanegobloku.Liczba zapisywanychbloków.fwrite( &num , sizeof( num ) , 1 , fp );Wskaźnik na zmienną num,która ma być zapisana dopliku fp.Zmienna ta, jest blokiemzapisywanym do pliku.Wskaźnik plikuotwartego do zapisu.Copyright © Roman Simiński Strona : 6


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hPrzetwarzanie plików binarnych, otwarcie pliku, zapis liczby typu floatZawartość pliku d.datSzesnastkowoJako tekstCopyright © Roman Simiński Strona : 7


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hOpis funkcji <strong>blokowe</strong>go zapisu — fwritesize_t fwrite( void * ptr, size_t size, size_t n, FILE * stream );Funkcja zapisuje dane z obszaru pamięci wskazywanego przez ptr do strumieniastream.Zapisuje n bloków o rozmiarze size.Łączna liczba zapisanych bajtów to n*size.Rezultatem funkcji jest liczba zapisanych bloków (nie bajtów!).W przypadku wystąpienia końca pliku lub błędu, rezultatem funkcji jest liczba,potencjalnie zerowa, bezbłędnie zapisanych bloków.Copyright © Roman Simiński Strona : 8


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hPrzetwarzanie plików binarnych, otwarcie pliku, odczyt liczby typu float#include #include int main(){FILE * fp;float num = 123.321;...num = 0;if( ( fp = fopen( "d.dat", "rb" ) ) != NULL ){fread( &num, sizeof( num ), 1, fp );printf( "\nOdczyt liczby: %g", num );fclose( fp );}}puts( "\n\nNacisnij Enter by zakonczyc..." );( void )getchar();return EXIT_SUCCESS;Copyright © Roman Simiński Strona : 9


Podstawy programowania w C++Odczyt i zapis z kontrolą poprawnościP r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hFunkcje fread i fwrite pozwalają na kontrolę poprawności wykonywanychoperacji odczytu i zapisu.Wystarczy kontrolować rezultat wywołania tych funkcji i porównywać z liczbąokreślonych bloków.if( ( fp = fopen( "d.dat", "wb" ) ) != NULL ){if( fwrite( &num, sizeof( num ), 1, fp ) != 1 )printf( "\nBlad zapisu!" );elseprintf( "\nZapis wykonany" );fclose( fp );}if( ( fp = fopen( "d.dat", "rb" ) ) != NULL ){if( fread( &num, sizeof( num ), 1, fp ) != 1 )printf( "\nBlad odczytu!" );elseprintf( "\nOdczyt liczby: %g", num );fclose( fp );}Copyright © Roman Simiński Strona : 12


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hZapis i odczyt ciągów danychZałóżmy, że zapisujemy do pliku 12-cie liczb typu float reprezentujących dochodyz kolejnych miesięcy roku podatkowego.Dane źródłowe są zapisane w dwunastoelementowej tablicy o nazwie d:#define LB_MIES 12. . .float d[ LB_MIES ];Pierwszym narzucającym się rozwiązaniem jest zapisanie kolejno każdegoelementu tablicy jako bloku, wykorzystując funkcję fwrite.Tablica0 1 2 34 5 6 78 9 10 11d2000 1530 2450 8003200 2560 1540 23002100 2800 3400 4200fwrite fwrite fwrite fwrite fwrite fwrite fwrite fwrite fwrite fwrite fwrite fwritePlik2000 1530 2450 8003200 2560 1540 23002100 2800 3400 4200EOF0 1 2 34 5 6 78 9 10 1112Copyright © Roman Simiński Strona : 13


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hZapis i odczyt ciągów danych, przykład 1-szy#include #include #define LB_MIES 12int main(){FILE * fp;float d[ LB_MIES ];int nr;/* Wstawiamy do tablicy przykładowe dane */for( nr = 0; nr < LB_MIES; nr++ )d[ nr ] = 1000 * ( nr + 1 );/* Zapis tablicy d, element po elemencie, do pliku d.dat */if( ( fp = fopen( "d.dat", "wb" ) ) != NULL ){for( nr = 0; nr < LB_MIES; nr++ )if( fwrite( &d[ nr ], sizeof( d[ nr ] ), 1, fp ) != 1 )printf( "\nBlad zapisu!" );elseprintf( "\nZapisano: %g", d[ nr ] );fclose( fp );}. . .Copyright © Roman Simiński Strona : 14


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hZapis i odczyt ciągów danych, rozwiązanie 2-gieCała tablica może być blokiem, zapisywanym/odczytywanym jednymwywołaniem instrukcji fwrite/fread.Tablica0 1 2 34 5 6 78 9 10 11d2000 1530 2450 8003200 2560 1540 23002100 2800 3400 4200fwrite lub freadPlik2000 1530 2450 8003200 2560 1540 23002100 2800 3400 4200EOF0 1 2 34 5 6 78 9 10 1112Copyright © Roman Simiński Strona : 16


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hZapis i odczyt ciągów danych, przykład 2-gi#include #include #define LB_MIES 12int main(){FILE * fp;float d[ LB_MIES ];int nr;/* Wstawiamy do tablicy przykładowe dane */for( nr = 0; nr < LB_MIES; nr++ )printf( "\nZapis: %g", d[ nr ] = 1000 * ( nr + 1 ) );if( ( fp = fopen( "d.dat", "wb" ) ) != NULL ){if( fwrite( &d[0], sizeof( d[0] ), LB_MIES, fp ) != LB_MIES )printf( "\nBlad zapisu!" );fclose( fp );}. . .Copyright © Roman Simiński Strona : 17


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hZapis i odczyt ciągów danych, uzupełnienieNazwa tablicy jest ustalonym wskaźnikiem na jej poczatek, czyli na pierwszyelement.Zatem zamiast &d[ 0 ] można napisać po prostu d:fread( &d[0], sizeof( d[0] ), LB_MIES, fp )fread( d, sizeof( d[0] ), LB_MIES, fp )Copyright © Roman Simiński Strona : 21


Podstawy programowania w C++Zapis i odczyt blokowy — dana typu intP r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hint zmienna_int = 10;FILE * fp;. . .if( fwrite( &zmienna_int, sizeof( zmienna_int ), 1, fp ) != 1 )printf( "\nBlad zapisu!" );elseprintf( "\nZapisano liczbe %d", zmienna_int );Możemy napisać funkcję, realizującą zapis pojedynczej danej typu int:int zmienna_int = 10;FILE * fp;. . .int write_int( int i, FILE * f ){return fwrite( &i, sizeof( i ), 1, f ) == 1;}if( ! write_int( zmienna_int, fp ) )printf( "\nBlad zapisu!" );elseprintf( "\nZapisano liczbe %d", zmienna_int );Copyright © Roman Simiński Strona : 22


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hZapis i odczyt blokowy — dana typu floatfloat zmienna_float = 10;FILE * fp;. . .if( fwrite( &zmienna_float, sizeof( zmienna_float ), 1, fp ) != 1 )printf( "\nBlad zapisu!" );elseprintf( "\nZapisano liczbe %g", zmienna_float );Możemy napisać funkcję, realizującą zapis pojedynczej danej typu float:float zmienna_float = 10;FILE * fp;. . .int write_float( float n, FILE * f ){return fwrite( &n, sizeof( n ), 1, f ) == 1;}if( ! write_float( zmienna_float, fp ) )printf( "\nBlad zapisu!" );elseprintf( "\nZapisano liczbe %g", zmienna_float );Copyright © Roman Simiński Strona : 23


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hWarto napisać sobie zestaw przydatnych funkcji. . .int write_int( int n, FILE * f ){return fwrite( &n, sizeof( n ), 1, f ) == 1;}int write_float( float n, FILE * f ){return fwrite( &n, sizeof( n ), 1, f ) == 1;}int write_double( double n, FILE * f ){return fwrite( &n, sizeof( n ), 1, f ) == 1;}int write_word( unsigned short int n, FILE * f ){return fwrite( &n, sizeof( n ), 1, f ) == 1;}. . .Copyright © Roman Simiński Strona : 24


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hKopiowanie zawartości plików blok po bloku/*-------------------------------------------------------------------------Funkcja bpb_file_copy realizuje kopiowanie zawartości źrodłowegopliku src do pliku docelowego dst. Wykorzystywane s ą <strong>blokowe</strong>operacje zapisu i odczytu. Funkcja nie zamyka strumieni src i dst.Parametry : Wskaźniki na prawidłowo otwarte strumienie binarnesrc, dst - odpowiednio dla pliku źródlowego i docelowego.Rezultat : 1 jeżeli kopiowanie zakończyło si ę poprawnie0 jeżeli wystąpił błąd podczas kopiowania-------------------------------------------------------------------------*/int bpb_file_copy( FILE * dst, FILE * src ){char * copy_buff = NULL; /* Wskaźnik na bufor kopiowania */size_t buff_size = 30 * 1024; /* Rozmiar bufora kopiowania */size_t in = 0; /* Liczba przeczytanych bloków */if( ( copy_buff = malloc( buff_size ) ) == NULL )return 0;while( ( in = fread( copy_buff, 1, buff_size, src ) ) != 0 )if( fwrite( copy_buff, 1, in, dst ) != in )return 0;}free( copy_buff );return 1;Copyright © Roman Simiński Strona : 25


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hUwaga, algorytm wykorzystuje drobny trikRozmiar odczytywanego bloku = 1 * buff_sizeRozmiar odczytywanegoelementu, uwaga: 1!Liczba odczytywanychelementów.while( ( in = fread( copy_buff, 1, buff_size, src ) ) != 0 )if( fwrite( copy_buff, 1, in, dst ) != in )return 0;Tutaj trafia liczbaodczytanych bloków 1-nobajtowych, czyli liczbaodczytanych bajtów.Zapisujemy tylebajtów, ileudało sieodczytać.Copyright © Roman Simiński Strona : 26


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hWyświetlanie zawartości pliku w widoku: szesnastkowo-ASCIIJakiś plik o dowolnej zawartości:while( ( in_chars = fread( buffer, 1, BUFFER_LEN, file ) ) > 0 ){/* Wypisz : hex, dwie pozycje, wiodące zera, duże litery */for( i = 0; i < in_chars; i++)printf( "%02X ", buffer[ i ] );printf("| "); /* Separator części szesnastkowej od ASCII */}}/* Wypisz bufor jako ASCII o ile można, jeśli nie to '.' */for( i = 0; i < in_chars; i++ )printf( "%c", isprint( buffer[ i ] ) ? buffer[ i ] : '.' );putchar('\n');Copyright © Roman Simiński Strona : 27


Podstawy programowania w C++P r z e t w a r z a n i e p l i k ó w a m o r f i c z n y c hWyświetlanie zawartości pliku w widoku: szesnastkowo-ASCII/*-------------------------------------------------------------------------Funkcja hex_dump wyprowadza do stdout zawartość pliku wyświetlanąw postaci szesnastkowej oraz ASCII.Parmetry : file - Wskaźnik na prawidłowo otwarty strumie ń binarnyUwaga – funkcja nie zatrzymuje wyświetlania np. co 24 linie.-------------------------------------------------------------------------*/void hex_dump( FILE * file ){#define BUFFER_LEN 19 /* Tyle znaków będzie w linii na ekranie */unsigned char buffer[ BUFFER_LEN ]; /* Bufor na odczytywane znaki */int i = 0;while( ( in_chars = fread( buffer, 1, BUFFER_LEN, file ) ) > 0 ){/* Wypisz : hex, dwie pozycje, wiodące zera, duże litery */for( i = 0; i < in_chars; i++)printf( "%02X ", buffer[ i ] );printf("| "); /* Separator części szesnastkowej od ASCII */}}/* Wypisz bufor jako ASCII o ile można, jeśli nie to '.' */for( i = 0; i < in_chars; i++ )printf( "%c", isprint( buffer[ i ] ) ? buffer[ i ] : '.' );putchar('\n');Copyright © Roman Simiński Strona : 28

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!