Шаг 293.
Язык программирования C#. Начала.
Немного о разном. Работа с файлами (продолжение)

    На этом шаге мы рассмотрим пример, где реализовано побайтовое копирование файла.

    В примере ниже представлена программа, при выполнении которой осуществляется побайтовое копирование файла: содержимое исходного (существующего) файла считывается байт за байтом и копируется в новый файл, который создается программой.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;

namespace pr293_1
{
    // Главный класс: 
    class Program
    {
        // Главный метод: 
        static void Main()
        {
            // Каталог с исходным файлом: 
            string pathFrom = "";
            // Каталог с новым файлом: 
            string pathTo = "";
            // Название исходного (копируемого) файла: 
            string file="bear.jpg";
            // Название для нового файла: 
            string name="animal.jpg";
            // Название и полный путь для файлов: 
            string f = pathFrom + file; 
            string F = pathTo + name;
            // Контролируемый код: 
            try {
                // Создание потока для считывания файла:
                FileStream fin = new FileStream(f, FileMode.Open);
                Console.WriteLine("Исходный файл: \"{0}\"", f);
                // Создание потока для записи в файл:
                FileStream fout = new FileStream(F, FileMode.Create);
                Console.WriteLine("Hoвый файл: \"{0}\"", F);
                // Целочисленная переменная: 
                int val;
                // Считывается первый байт из потока: 
                val = fin.ReadByte();
                // Чтение и запись байтов: 
                while(val != -1) {
                    // Запись байта в поток: 
                    fout.WriteByte((byte)val);
                    // Считывается байт из потока: 
                    val = fin.ReadByte();
                }
                // Закрываются потоки:
                fout.Close();
                fin.Close();
            }
            // Обработка исключений: 
            catch(Exception e) {
                Console.WriteLine("Произошла ошибка!");
                Console.WriteLine(e.Message);
                // Задержка:
                Console.ReadLine();
                return; // Завершение выполнения программы
            }
            Console.WriteLine("Копирование успешно завершено");
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    При успешном выполнении программы в консольном окне появляются такие сообщения:


Рис.1. Результат работы приложения

    Но главный результат выполнения программы иной: в каталоге bin/Debug проекта появляется файл animal.jpg, который является копией файла bear.jpg из этого же каталога.


Разумеется, перед запуском программы на выполнение в каталог bin/Debug проекта нужно поместить файл bear.jpg. Альтернатива: указать в программе другой каталог и другой исходный файл. Но если, несмотря на все усилия, при выполнении программы возникает ошибка (связанная, например, с отсутствием исходного файла в указанном каталоге), то в процессе обработки исключения отображается сообщение о том, что возникла ошибка, и описание этой ошибки (значение свойства Message объекта исключения).

    В самой программе в текстовые переменные f и F записывается полный путь к исходному файлу и файлу, который должен быть создан в процессе копирования. Текстовая переменная f передается в качестве аргумента конструктору класса FileStream при создании объекта потока fin. Это поток используется для считывания содержимого исходного файла. Второй аргумент конструктора FileMode.Open означает, что речь идет об открытии существующего файла. Текстовая переменная F передается первым аргументом конструктору класса FileStream при создании объекта потока fout. Поток предназначен для записи байтовых данных в файл, который создается при создании объекта потока (поэтому вторым аргументом конструктору передана константа FileMode.Open).

    Для запоминания считанных байтов мы используем переменную val типа int. Командой

  val = fin.ReadByte(); 
в эту переменную записывается первый байт из потока, связанного с исходным файлом. После этого запускается цикл while, в котором проверяется условие val!=-1. Здесь мы учли, что если достигнут конец файла, то при попытке прочитать очередной байт с помощью метода ReadByte() возвращается значение -1. Поэтому истинность условия val!=-1 означает, что конец файла не достигнут. Если так, то командой
  fout.WriteByte((byte)val); 
этот байт записывается в поток fout, после чего командой
  val = fin.ReadByte(); 
считывается очередной байт из потока fin.


Метод ReadByte() считывает байт, но возвращает значение типа int. Значение типа byte не может быть отрицательным. Значение -1, возвращаемое методом при достижении конца файла, является целочисленным (типа int). Поэтому результат метода заносится в переменную типа int. Но при записи байта в поток это int-значение необходимо преобразовать в byte-значение.

    После завершения конструкции цикла, когда копирование выполнено, командами

  fout.Close();
и
  fin.Close(); 
оба потока закрываются.

    На следующем шаге мы рассмотрим другой способ копирования файла.




Предыдущий шаг Содержание Следующий шаг