СПЗ отчеты (Власенко О.В.) / 1
.docМіністерство освіти, науки, молоді та спорту України
Житомирський державний технологічний університет
ФІКТ
Кафедра ПЗОТ
Група ПІК-9
Лабораторна робота №1
Програми копіювання файлів
Виконав : Оленюк О.О.
Перевірив : Власенко О.В.
Житомир
2012 р.
Завдання:
-
Навчитися користуватись програмами copy1.exe та copy2.exe.
-
Розібрати роботу програм.
-
В програмі copy1.c замінити бінарний режим доступу до обох файлів на текстовий і запустити програму для копіювання досить великого бінарного файлу. Результати експерименту зафіксувати в зошиті. Пояснити причину ефекту.
-
В програмі copy1.c замінити бінарний режим доступу до файлу, який записується, на текстовий і запустити програму. Результати експерименту зафіксувати в зошиті. Пояснити причину ефекту.
-
В програмі copy2.c знайти оптимальний розмір буферу. Обгрунтувати вибір.
-
В програмі copy2.c модифікувати програму так, щоб вона виводила на екран вміст файлу за допомогою функцій puts(), fputs, printf(), fwrite().Результати експерименту зафіксувати в зошиті. Пояснити причину ефекту.
Виконання роботи
-
Розбираємо програму copy1.c
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <alloc.h>
#include <errno.h> // Підключення бібліотек
#define BUFSIZE 10000 // Оголошення константи
void main( int argc, char **argv ) { // Доступ до командної строчки
int source, target;
int i;
char *buffer; // Оголошення змінних
int count;
if( argc != 3 ) {
printf( "\n" "Usage: COPY1 [d:][\\path]source_file [d:][\\path]target_file \n" );
exit( 1 );
} // В разі невідповідності кількості констант виводиться повідомлення про правильність написання.
if( ( source = open( argv[ 1 ], O_BINARY | O_RDONLY ) ) == -1 ) {
printf( "\n Open source file error: %d", errno );
exit( 2 );
} // Відбувається відкриття нашого початкового файлу, бінарний доступ, тільки читання.
target = open( argv[ 2 ], O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
S_IREAD | S_IWRITE );
// Відбуваєть створення файду з можливістю подальшого читання та запису в нього, бінарний доступ, відкривається тільки для запису і в режимі виняткового доступу.
if( errno == EEXIST ) {
printf( "\n File already exists. Overwrite? (Y/N) \n" );
i = getch();
if( ( i == 'y' ) || ( i == 'Y' ) )
target = open( argv[ 2 ], O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE );
} // В разі виникнення помилки типу “Файл уже існує” вивводиться повідомлення, при необхідності перезапису, файл створюється знову з відсіканням попереднього змісту
if( target == -1 ) {
printf( "\n Open target file error: %d", errno );
exit( 2 );
} // Відбувається спроба відкрити кінцевий файлу, в разі неможливості виводиться помилка
count = BUFSIZE;
if( ( buffer = ( char* )malloc( count ) ) == NULL ) {
printf( "\n Not enough memory" );
exit( 3 );
} // Перевіряється наявність вільної пам’яті на диску, в разі її відсутності – виводиться помилка
while( !eof( source ) ) {
if( ( count = read( source, buffer, count ) ) == -1 ) {
printf( "\n Read file error: %d", errno );
exit( 4 );
}
// Відбувається читання початкового файлу,
if( ( count = write( target, buffer, count ) ) == -1 ) {
printf( "\n Write file error: %d", errno );
exit( 5 );
}
// Відбувається запис в кінцевий файл
}
close( source );
close( target );
free( buffer );
} // Закриття обох файлів, вивільнення буферу
-
Розбираємо програму COPY2.C
#include <stdio.h>
#include <stdlib.h>
#include <time.h> // Підключення бібліотек
void filecpy( FILE *stream_from, FILE *stream_to ); // Доступ до командної строчки
char buf1[ BUFSIZ * 10 ];
char buf2[ BUFSIZ * 10 ]; ; // Оголошення змінних
void main( int argc, char *argv[] ) {
time_t start, end;
FILE *stream_from, *stream_to;
if( argc < 3 ) {
printf( "\nUsage:"
" COPY2 [d:][\\path]source_file [d:][\\path]target_file\n" );
exit( 1 );
}
// В разі невідповідності кількості констант виводиться повідомлення про правильність написання.
// Проводимо копіювання файлу з буфером стандартного розміру (512 b)
if( ( stream_from = fopen( argv[ 1 ], "rt" ) ) == NULL ) {
printf( "\nOpen source file error: %d", errno );
exit( 1 );
}
// Відкриваємо файл для читання в текстовому режимі та копіюємо його за допомогою буферу стандартного розміру
stream_to = fopen( argv[ 2 ], "wt+" );
// Відкриваємо другий файл для запису в текстовому режимі
start = clock(); // Визначаємо час початку копіювання
filecpy( stream_from, stream_to ); // За допомогою спеціальної функції проводимо копіювання
end = clock(); // Визначаємо час закінчення копіювання
printf( "Copying time is %5.1f. Buffer size is %d bytes\n",
( ( float )end - start ) / CLK_TCK, BUFSIZ ); // Виводимо результат
// Проводимо копіювання файлу з буфером більшого розміру (5120 b)
if( ( stream_from = fopen( argv[ 1 ], "rt") ) == NULL )
exit( 1 );
stream_to = fopen( argv[ 2 ], "wt+" );
setvbuf( stream_from, buf1, _IOFBF, sizeof( buf1 ) ); // Визначаємо розмір буферу для першого файлу
setvbuf( stream_to, buf2, _IOFBF, sizeof( buf2 ) ); // Визначаємо розмір буферу для другого файлу
start = clock();
filecpy( stream_from, stream_to );
end = clock();
printf( "Copying time is %5.1f. Buffer size is %d bytes\n",
( ( float )end - start ) / CLK_TCK, BUFSIZ * 10 );
// Проводимо копіювання файлу без використання буферизації
if( ( stream_from = fopen( argv[ 1 ], "rt") ) == NULL )
exit( 1 );
stream_to = fopen( argv[ 2 ], "wt+" );
setvbuf( stream_from, NULL, _IONBF, 0 ); // Визначаємо нульовий розмір буферу
setvbuf( stream_to, NULL, _IONBF, 0 ); // Визначаємо нульовий розмір буферу
start = clock();
filecpy( stream_from, stream_to );
end = clock();
printf( "Copying time is %5.1f. Buffers is not used\n",
( ( float )end - start ) / CLK_TCK );
exit( 0 );
}
/****************************************************************************
* filecpy - функция копирования файлов с использованием потоков ввода/вывода
* Args: stream_from - поток, откуда копировать;
* stream_to - поток, куда копировать;
* Return: none.
* Globals:none.
****************************************************************************/
// Задаємо параметри нашої функції filecpy
void filecpy( FILE *stream_from, FILE *stream_to ) {
char linebuf[ 256 ];
while( !feof( stream_from ) ) {
if( fgets( linebuf, 255, stream_from ) == NULL ) break;
if( fputs( linebuf, stream_to ) == EOF ) break;
}
fclose( stream_from );
fclose( stream_to );
}
3. В програмі copy1.c при заміні бінарного режиму доступу до обох файлів на текстовий і запустивши програму отримуємо дуже маленький вихідний файл який не відповідає початковому. Це викликано тим, що в текстовому режимі доступу, як тільки з файлу зчитується символ Ctrl-Z (ASCII 1Ah), вважається, що досягнуто кінець файлу (умова EOF). І подальший запис припиняеться, що і відбулося в нашому випадку.
4. В програмі copy1.c при заміні бінарного режим доступу до файлу, який записується, на текстовий і запустивши программу отримуємо файл, по розміру майже схожий з нашим початковим, але відкриття якого неможливе. Це викликано тим, що початковий файл був відкритий за допомогою бінарного доступу, а кінцевий в текстовому режимі, саме через цю розбіжність у кінцевому файлі не відбулася обернена трансляція символів.
5. Запустивши програму copy2.c для копіювання файлу досить великого розміру (5 Мb) отримуємо такі вихідні результати програми:
Copying time is 0.7. Buffer size is 512 bytes
Copying time is 0.5. Buffer size is 5120 bytes
Copying time is 14.5. Buffers is not used
З побаченого можна зробити висновок, що в даних випадках оптимальний розмір буферу являє собою 512 біт. Тому що в порівнянні з буфером в 5120 біт, різниця в часі між ними лише в 0.2 секунди, що є досить малою, з врахуванням того що буфер в 5120 біт в десять разів більшим. Ну а не використання буферизації взагалі призводить до значних затрат часу.
6. В програмі copy2.c модифікуємо програму так, щоб вона виводила на екран вміст файлу за допомогою функцій puts(), fputs, printf(), fwrite(). В результаті наші функції матимуть вигляд:
puts(buf1); // Функція виводить вміст буферу (buf1) на стандартний пристрій виведення, а саме на монітор.
fputs(buf1,stdout); // Функція виводить вміст буферу (buf1) в параметр stdout, що являє собою монітор.
printf("Sodergimoe fayla:\n %s", buf1); // стандартна функція виведення значення змінної buf1.
fwrite(buf1, sizeof(buf1), 1, stdout); // Копіює вміст buf1, коміркою розміром buf1, один раз, на монітор.
//Доступ до файлів на низькому рівні – через дескриптори (описувач), на високому – через потоки.
Дискриптор – це число, яке задає номер певного ресурсу (блок пам'яті, файл, курсор, шрифт…) під час роботи з ним.
Чому не відбувається копіювання двійкових файлів через символьний режим.