Книга: Системное программирование в среде Windows

Копирование файлов с использованием стандартной библиотеки С

Копирование файлов с использованием стандартной библиотеки С

Как видно из текста программы 1.1, стандартная библиотека С поддерживает объекты потоков ввода/вывода FILE, которые напоминают, несмотря на меньшую общность, объекты Windows HANDLE, представленные в программе 1.2.

Программа 1.1. срC: копирование файлов с использованием библиотеки С

/* Глава 1. Базовая программа копирования файлов cp. Реализация, использующая библиотеку С. */
/* cp файл1 файл2: Копировать файл1 в файл2. */
#include <stdio.h>
#include <errno.h>
#define BUF_SIZE 256
int main(int argc, char *argv[]) {
 FILE *in_file, *out_file;
 char rec [BUF_SIZE];
 size_t bytes_in, bytes_out;
 if (argc != 3) {
  printf("Использование: срС файл1 файл2n");
  return 1;
 }
 in_file = fopen(argv [1], "rb");
 if (in_file == NULL) {
  perror(argv[1]);
  return 2;
 }
 out_file = fopen(argv [2], "wb");
 if (out_file == NULL) {
  perror(argv [2]);
  return 3;
 }
 /* Обработать входной файл по одной записи за один раз. */
 while ((bytes_in = fread(rec, 1, BUF_SIZE, in_file)) > 0) {
  bytes_out = fwrite(rec, 1, bytes_in, out_file);
  if (bytes_out != bytes_in) {
   perror("Неустранимая ошибка записи.");
   return 4;
  }
 }
 fclose (in_file);
 fclose (out_file);
 return 0;
}

Этот простой пример может служить наглядной иллюстрацией ряда общепринятых допущений и соглашений программирования, которые не всегда применяются в Windows.

1. Объекты открытых файлов идентифицируются указателями на структуры FILE (в UNIX используются целочисленные дескрипторы файлов). Указателю NULL соответствует несуществующий объект. По сути, указатели являются разновидностью дескрипторов объектов открытых файлов.

2. В вызове функции fopen указывается, каким образом должен обрабатываться файл — как текстовый или как двоичный. В текстовых файлах содержатся специфические для каждой системы последовательности символов, используемых, например, для обозначения конца строки. Во многих системах, включая Windows, в процессе выполнения операций ввода/вывода каждая из таких последовательностей автоматически преобразуется в нулевой символ, который интерпретируется в языке С как метка конца строки, и наоборот. В нашем примере оба файла открываются как двоичные.

3. Диагностика ошибок реализуется с помощью функции perror, которая, в свою очередь, получает информацию относительно природы сбоя, возникающего при вызове функции fopen, из глобальной переменной errno. Вместо этого можно было бы воспользоваться функцией ferror, возвращающей код ошибки, ассоциированный не с системой, а с объектом FILE.

4. Функции fread и fwrite возвращают количество обработанных байтов непосредственно, а не через аргумент, что оказывает существенное влияние на логику организации программы. Неотрицательное возвращаемое значение говорит об успешном выполнении операции чтения, тогда как нулевое — о попытке чтения метки конца файла.

5. Функция fclose может применяться лишь к объектам типа FILE (аналогичное утверждение справедливо и в отношении дескрипторов файлов UNIX).

6. Операции ввода/вывода осуществляются в синхронном режиме, то есть прежде чем программа сможет выполняться дальше, она должна дождаться завершения операции ввода/вывода.

7. Для вывода сообщений об ошибках удобно использовать входящую в библиотеку С функцию ввода/вывода printf, которая даже будет использована в первом примере Windows-программы.

Преимуществом реализации, использующей библиотеку С, является ее переносимость на платформы UNIX, Windows, а также другие системы, которые поддерживают стандарт ANSI С. Кроме того, как показано в приложении В, в том, что касается производительности, вариант, использующий функции ввода/вывода библиотеки С, ничуть не уступает другим вариантам реализации. Тем не менее, в этом случае программы вынуждены ограничиваться синхронными операциями ввода/вывода, хотя влияние этого ограничения будет несколько ослаблено использованием потоков Windows (начиная с главы 7).

Как и их эквиваленты в UNIX, программы, основанные на функциях для работы с файлами, входящих в библиотеку С, способны выполнять операции произвольного доступа к файлам (с использованием функции fseek или, в случае текстовых файлов, функций fsetpos и fgetpos), но это является уже потолком сложности для функций ввода/вывода стандартной библиотеки С, выше которого они подняться не могут. Вместе с тем, Visual C++ предоставляет нестандартные расширения, способные, например, поддерживать блокирование файлов. Наконец, библиотека С не позволяет управлять средствами защиты файлов.

Резюмируя, можно сделать вывод, что если простой синхронный файловый или консольный ввод/вывод — это все, что вам надо, то для написания переносимых программ, которые будут выполняться под управлением Windows, следует использовать библиотеку С.

Оглавление книги


Генерация: 1.253. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз