- •Литература
- •Содержание
- •1. Основные понятия ооп
- •2. Программирование для Windows
- •3. Визуальное программирование и среда Delphi
- •Создание приложений в средеDelphi
- •Компоненты общего назначения tMainMenu- главное меню формы (программы)
- •TPopupMenu- вспомогательное (локальное) меню
- •TLabel- метка для отображения текста
- •TEdit-ввод и отображение строки
- •TMemo- ввод и отображение текста
- •TButton- кнопка
- •TBitBtn- кнопка с изображением
- •TSpeedButton- кнопка для инструментальных панелей
- •TCheckBox- независимый переключатель
- •TRadioButton- зависимые переключатели
- •TRadioGroup- группа зависимых переключателей
- •TListBox- список выбора
- •TComboBox- раскрывающийся список выбора
- •TPanel- панель
- •TTabControl- набор закладок
- •TPageControl- набор страниц с закладками
- •4. Особенности языка ооп Object Pascal
- •Процедуры и функции Выход из процедур и фукнций и возврат результата
- •Передача параметров
- •Параметры со значениями по умолчанию
- •Перегрузка функций
- •Динамическое распределение памяти
- •Указатели
- •Операции с указателями
- •Операция @
- •Самоадресуемые записи
- •Динамические массивы Одномерные динамические массивы
- •Многомерные динамические массивы
- •Исключения и их обработка
- •Защита кода зачистки в блокахtry...Finally
- •Защита кода зачистки на уровне модуля — разделfinalization
- •Обработка исключений в блокахtry...Except
- •Последовательность обработки исключений
- •5. Классы и объекты
- •Классы и объекты
- •Инкапсуляция
- •Наследование
- •Полиморфизм
- •Составляющие класса Поля
- •Одноименные методы
- •Свойства
- •События
- •Объявление класса
- •Операции с классами
- •Ссылки на классы
- •TObjectи информация о классах
- •Регистрация и обнаружение классов
- •6. Создание объектов во время выполнения, поиск компонентов
- •Клонирование объектов
- •Поиск компонента
- •Двукратное освобождение объекта
- •7. Построение собственных компонентов
- •Как и для чего следует строить компоненты
- •Общие руководящие принципы
- •Ключевые идеи
- •Компиляция компонентов
- •Отладка компонентов
- •Примечание
- •Примечание
- •Примечание
- •8. Работа с потоками
- •Классы потоковDelphi
- •Файловые потоки
- •Примечание
- •Методы потоков в действии: программаMemoStr
- •Потоки памяти
- •Пример программыMemoryS
- •Примечание
- •Написание заказного класса потока
- •9. Работа с com-объектами, использование серверов ole-автоматизации
8. Работа с потоками
Обычные программы, написанные на языке Pascal, управляют файлами несколькими способами, такими как, например, использование стандартных функций и процедур языка Pascal для работы с файлами DOS и Windows. Однако Delphi представляет новую концепцию — поток (stream) и использует ее достаточно интенсивно: класс TStream и его наиболее общие производные — классы TReader и TWriter, класс TPersistent и класс TComponent.
Классы потоковDelphi
Если вы не знакомы с потоками как понятием программирования, необходимо уяснить основной смысл потоков в природе. Каждый поток имеет определенное начало и конец, и, как правило, можно определить текущую позицию относительно начала и конца потока. Кроме того, при возвращении к той же самой позиции в потоке, отсутствует гарантия возврата к «той же воде, тем же водорослям или рыбе».
Точно так же в программировании поток имеет начало и конец, и можно определить позицию в потоке относительно тех же точек. Как и в естественных потоках, отсутствует гарантия, что та же самая позиция в данном потоке содержит те же самые данные. Размышляя над этим, можно, вероятно, подумать о многих типах данных, чье поведение соответствует потоку, например, о блоках памяти, файлах на диске или даже о последовательности байтов, передаваемых на последовательный или параллельный порт.
Модуль Classes в VCL определяет абстрактный класс, названный TStream, и несколько классов прямых потомков.
• TFileStream определяет поток, управляющий файлом на диске (файлом, существующим на локальном или сетевом диске), используя имя файла. Данное свойство наследуется из класса THandleStream.
• THandleStream определяет поток, управляющий файлом на диске, используя дескриптор handle файла Windows.
• TMemoryStream определяет поток, управляющий последовательностью байтов в памяти, наследуемый из TCustomMemoryStream.
• TResourceStream определяет поток, который управляет последовательностью байтов в памяти, а также обеспечивает возможности преобразования ресурса. Он наследуется из
TCustomMemoryStream.
• TBlobStream определяет поток, обеспечивающий простой доступ к полям данных BLOB.
• TVirtualStream определяет редко документированный класс, используемый интерфейсами инструментов Delphi Tool Services (или ToolsAPI).
• TOleStreamObject (представленный в Delphi 3) определяет поток для чтения и записи информации через интерфейс для работы с потоками, предоставляемый в OLE.
• TStringStream (представленный в Delphi 3) обеспечивает простой способ использования потока для длинной строки.
• TWinSocketStream (представленный в Delphi 3) обеспечивает поддержку потоков, подключаемых через соединительные разъемы.
Класс TStream определяет два свойства: размер size и позицию Position, являющиеся общими для всех классов потоков. Если воспринимать поток как подобие фрагмента провода или строки, получается полезная рабочая аналогия. Любой определенный фрагмент провода, веревки или строки имеет размер (определенную длину), и обычно материал обрабатывается в определенной позиции в пределах длины. Единицы измерения позиции и длины (дюймы, сантиметры, или нечто другое) может меняться от одного материала к другому, но смысл остается тем же.
Точно так же все объекты потока Delphi имеют особый размер, и приходится определять позицию внутри потока, где требуется либо чтение, либо запись информации. Чтение и запись байтов в THandleStream дает не такой результат, как чтение и запись полей в базе данных BLOB, но в обоих случаях вам нет необходимости знать намного больше, чем размер потока и текущую позицию в потоке для чтения или записи данных. Это одно из преимуществ использования потоков. Базисный интерфейс остается тем же самым при управлении файлом на диске, полем BLOB или длинной последовательностью байтов в памяти.
В дополнение к свойствам Size и Position, класс TStream также определяет несколько важных методов, большинство из которых являются виртуальными и абстрактными. (Другими словами, класс TStream не определяет то, что делают эти методы; следовательно, порожденные классы сами отвечают за выполнение.) Некоторые из этих методов важны только в контексте чтения или записи компонентов внутри потока (например, ReadComponent и WriteComponent), но некоторые из этих методов также полезны и в других контекстах. Вот объявление класса TStream:
TStream = class(TObject)
public
// чтение и запись буфера
function Read(var Buffer; Count: Longint): Longint;virtual; abstract;
function Write(const Buffer; Count: Longint): Longint;virtual; abstract;
procedure ReadBuffer(var Buffer; Count: Longint);
procedure WriteBuffer(const Buffer; Count: Longint); // перемещение на заданную позицию function Seek(Offset: Longint; Origin: Word): Longint;virtual; abstract; // копирование потока
function CopyFrom(Source: TStream; Count: Longint): Longint; // чтение или запись компонента
function ReadComponent(Instance: TComponent): TComponent;
function ReadComponentRes(Instance: TComponent): TComponent;
procedure WriteComponent(Instance: TComponent);
procedure WriteComponentRes(
const ResName: string; Instance: TComponent);
procedure WriteDescendent(Instance, Ancestor: TComponent);
procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
procedure ReadResHeader;
// свойства
property Position: Longint read GetPosition write SetPosition;
property Size: Longint read GetSize;
end;
Очевидно, что нет смысла пробовать создавать объект TStream, так как этот класс не определяет способ чтения или записи данных в поток. Вместо этого класс TStream определяет стандартный интерфейс для всех классов потока. Пытаясь создать объект TStream и обратиться к методам при выполнении программы, вероятнее всего сгенерируется ошибка 102 периода выполнения, указывающая, что ваша программа вызвала абстрактную функцию, не обеспечив реализацию этой функции.
Вместо этого необходимо стремиться создавать экземпляры одного из производных классов, типа TFileStream. Этот подход очень упрощает манипуляции с данными файла на диске.