Что такое поток? Поток, проще говоря, — это абстрактная обработка данных, основанная на объектно-ориентированном подходе.
инструменты. В потоке определяются некоторые основные операции обработки данных, такие как чтение данных, запись данных и т. д.
Программист выполняет все операции над потоком, не заботясь о фактическом направлении потока данных на другом конце потока. Поток не
Но он может обрабатывать файлы, динамическую память, сетевые данные и другие формы данных. если ты прав
Работа с потоками очень эффективна. Использование потоков в программах значительно повысит эффективность написания программ.
Ниже автор использует четыре примера: шифратор EXE-файлов, электронная поздравительная открытка, самодельный OICQ и сетевой экран.
Передача, чтобы проиллюстрировать использование «потока» в программировании на Delphi. Некоторые из техник в этих примерах раньше были очень мягкими.
Секрет файла не разглашается, и теперь каждый может бесплатно напрямую процитировать код.
«Высокие здания поднимаются из земли». Прежде чем разбирать примеры, давайте сначала разберемся с основными понятиями и понятиями потока.
Функции, только после понимания этих основных вещей мы можем перейти к следующему шагу. Пожалуйста, поймите внимательно
эти основные методы. Конечно, если вы с ними уже знакомы, этот шаг можно пропустить.
1. Основные понятия и объявления функций потоков в Delphi
В Delphi базовым классом всех объектов потока является класс TStream, который определяет общие свойства всех потоков.
и методы.
Свойства, определенные в классе TStream, представлены следующим образом:
1. Размер. Это свойство возвращает размер данных в потоке в байтах.
2. Позиция: этот атрибут управляет положением указателя доступа в потоке.
В Tstream определены четыре виртуальных метода:
1. Чтение. Этот метод считывает данные из потока. Прототип функции:
Функция Read(var Buffer;Count:Longint):Longint;виртуальный;абстрактный;
Параметр Buffer — это буфер, помещаемый при чтении данных, Count — количество байтов данных, которые необходимо прочитать,
Возвращаемое значение этого метода — это фактическое количество прочитанных байтов, которое может быть меньше или равно значению, указанному в Count.
2. Запись. Этот метод записывает данные в поток. Прототип функции:
Функция Write(var Buffer;Count:Longint):Longint;виртуальный;абстрактный;
Параметр Buffer — это буфер данных, которые будут записываться в поток, Count — длина данных в байтах,
Возвращаемое значение этого метода — это количество байтов, фактически записанных в поток.
3. Поиск. Этот метод реализует перемещение указателя чтения в потоке. Прототип функции:
Функция Seek(Смещение:Longint;Origin:Word):Longint;виртуальный;абстрактный;
Параметр Offset — это количество байтов смещения, а параметр Origin указывает фактическое значение Offset и его возможные значения.
следующее:
soFromBeginning:Offset — это позиция указателя от начала данных после перемещения. В это время Offset должен
Больше или равно нулю.
soFromCurrent:Offset — это относительное положение указателя после перемещения и текущего указателя.
soFromEnd:Offset — позиция указателя от начала данных после перемещения. В это время Offset должен
Меньше или равно нулю.
Возвращаемое значение этого метода — это позиция указателя после перемещения.
4. Setsize: этот метод изменяет размер данных. Прототип функции:
Функция Setsize(NewSize:Longint);virtual;
Кроме того, в классе TStream также определено несколько статических методов:
1. ReadBuffer: функция этого метода — чтение данных из текущей позиции в потоке. Прототип функции:
PROcedure ReadBuffer(var Buffer;Count:Longint);
Определение параметров такое же, как описано выше. Примечание. Когда количество прочитанных байтов данных отличается от количества байтов, которые необходимо прочитать.
Если числа разные, будет сгенерировано исключение EReadError.
2. WriteBuffer: функция этого метода — запись данных в поток в текущей позиции. Прототип функции:
Процедура WriteBuffer(var Buffer;Count:Longint);
Определение параметров такое же, как и в Write выше. Примечание. Когда количество записанных байтов данных отличается от количества байтов, которые необходимо записать.
Если числа различаются, будет сгенерировано исключение EWriteError.
3. CopyFrom: этот метод используется для копирования потоков данных из других потоков. Прототип функции:
Функция CopyFrom(Source:TStream;Count:Longint):Longint;
Параметр Source — это поток, предоставляющий данные, а Count — это количество скопированных байтов данных. Когда Count больше 0,
CopyFrom копирует Count байтов данных из текущей позиции параметра Source, когда Count равен 0;
CopyFrom устанавливает для свойства Position параметра Source значение 0, а затем копирует все данные источника;
У TStream есть и другие производные классы, наиболее часто используемым из которых является класс TFileStream. Использование TFileStream
Чтобы получить доступ к файлам с помощью класса, вы должны сначала создать экземпляр. Заявление заключается в следующем:
конструктор Create(const Filename:string;Mode:Word);
Имя файла — это имя файла (включая путь), а параметр Mode — это способ открытия файла, который включает способ открытия файла.
Открытый режим и общий режим, их возможные значения и значения следующие:
Открытый режим:
fmCreate: создайте файл с указанным именем или откройте файл, если он уже существует.
fmOpenRead: открыть указанный файл в режиме только для чтения.
fmOpenWrite: открыть указанный файл в режиме только для записи.
fmOpenReadWrite: открыть указанный файл для записи.
Режим обмена:
fmShareCompat: режим общего доступа совместим с FCB.
fmShareExclusive: Не разрешать другим программам каким-либо образом открывать файл.
fmShareDenyWrite: не разрешать другим программам открывать файл для записи.
fmShareDenyRead: не разрешать другим программам открывать файл в режиме чтения.
fmShareDenyNone: другие программы могут открыть файл любым способом.
У TStream также есть производный класс TMemoryStream, который очень часто используется в реальных приложениях.
Очень часто. Это называется потоком памяти, что означает создание объекта потока в памяти. Его основные методы и функции следуют
То же, что и выше.
Что ж, имея вышеуказанную основу, мы можем начать наше путешествие по программированию.
-------------------------------------------------- --------------------------
2. Первое практическое применение: использование потоков для создания шифраторов EXE-файлов, пакетов, самораспаковывающихся файлов и программ установки.
Давайте сначала поговорим о том, как сделать шифратор EXE-файлов.
Принцип шифрования EXE-файлов: создайте два файла, один из которых используется для добавления ресурсов в другой EXE-файл.
Внутри это называется надстройкой. Другой добавляемый EXE-файл называется файлом заголовка. Функция этой программы
Прочитайте файлы, добавленные к себе.
Структура EXE-файлов в Windows относительно сложна. Некоторые программы также имеют контрольные суммы, когда вы обнаруживаете, что они были изменены.
Позже они подумают, что заражены вирусом, и откажутся его выполнять. Итак, мы добавляем файл в нашу программу,
Это не изменит исходную структуру файла. Давайте сначала напишем функцию добавления. Функция этой функции — сложение.
Один файл добавляется в конец другого файла в виде потока. Функция следующая:
Функция Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
вар
Цель, Источник: TFileStream;
MyFileSize: целое число;
начинать
пытаться
Источник:=TFileStream.Create(SourceFile,fmOpenRead или fmShareExclusive);
Target:=TFileStream.Create(TargetFile,fmOpenWrite или fmShareExclusive);
пытаться
Target.Seek(0,soFromEnd);//Добавляем ресурсы в конец
Target.CopyFrom(Источник,0);
MyFileSize:=Source.Size+Sizeof(MyFileSize);//Рассчитываем размер ресурса и записываем его в конец вспомогательного процесса
Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));
окончательно
Цель.Бесплатно;
Источник.Бесплатно;
конец;
кроме
Результат: = Ложь;
Выход;
конец;
Результат:=Истина;
конец;
Имея вышеизложенное, мы должны легко понять эту функцию. где параметр SourceFile
Файл, который нужно добавить, параметр TargetFile — это целевой файл, который нужно добавить. Например, добавьте файл .exe в
В b.exe вы можете: Cjt_AddtoFile('a.exe',b.exe'); если добавление прошло успешно, в противном случае вернуть True.
Вернуть ложь.
На основе приведенной выше функции мы можем написать противоположную функцию чтения:
Функция Cjt_LoadFromFile(SourceFile,TargetFile:string):Boolean;
вар
Источник: TFileStream;
Цель:TMemoryStream;
MyFileSize: целое число;
начинать
пытаться
Цель:=TMemoryStream.Create;
Источник:=TFileStream.Create(SourceFile,fmOpenRead или fmShareDenyNone);
пытаться
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//Читать размер ресурса
Source.Seek(-MyFileSize,soFromEnd);//Определение местоположения ресурса
Target.CopyFrom(Source,MyFileSize-sizeof(MyFileSize));//Удалить ресурсы
Target.SaveToFile(TargetFile);//Сохранить в файл
окончательно
Цель.Бесплатно;
Источник.Бесплатно;
конец;
кроме
Результат: = ложь;
Выход;
конец;
Результат:=истина;
конец;
Параметр SourceFile — это имя добавляемого файла, а параметр TargetFile — это имя удаленного файла.
Имя целевого файла, которое будет сохранено после файла. Например, Cjt_LoadFromFile('b.exe','a.txt');
Выньте файл и сохраните его как .txt. Если извлечение прошло успешно, оно возвращает True, в противном случае — False.
Откройте Delphi, создайте новый проект и поместите в окно элемент управления Edit Edit1 и две кнопки:
Кнопка1 и Кнопка2. Свойству кнопки Caption присвоено значение «ОК» и «Отмена» соответственно. существовать
Напишите код в событии Click кнопки Button1:
вар S: строка;
начинать
S:=ChangeFileExt(application.ExeName,'.Cjt');
если Edit1.Text='790617', то
начинать
Cjt_LoadFromFile(Application.ExeName,S);
{Извлеките файл и сохраните его по текущему пути и назовите его "исходный файл.Cjt"}
Winexec(pchar(S),SW_Show);{Запустить "исходный файл.Cjt"}
Application.Terminate;{Выход из программы}
конец
еще
Application.MessageBox('Пароль неверен, пожалуйста, введите его еще раз!', 'Пароль неверен', MB_ICONERROR+MB_OK);
Скомпилируйте эту программу и переименуйте EXE-файл в head.exe. Создайте новый текстовый файл head.rc,
Содержимое: head exefile head.exe, затем скопируйте его в каталог BIN Delphi и выполните.
Команда Dos Brcc32.exe head.rc создаст файл head.res. Этот файл нам нужен.
Файлы ресурсов, сохраните их в первую очередь.
Наш заголовочный файл создан, приступим к созданию надстройки.
Создайте новый проект и поместите следующие элементы управления: один Edit, один Opendialog и два Button1.
Для свойств «Заголовок» установлены значения «Выбрать файл» и «Зашифровано» соответственно.
Добавьте предложение в исходную программу: {$R head.res} и скопируйте файл head.res в текущий каталог программы.
Таким образом, head.exe только что компилируется вместе с программой.
Напишите код в событии Cilck Button1:
если OpenDialog1.Execute, то Edit1.Text:=OpenDialog1.FileName;
Напишите код в событии Cilck Button2:
вар S:Строка;
начинать
S:=ExtractFilePath(Edit1.Text);
если ExtractRes('exefile','head',S+'head.exe') тогда
если Cjt_AddtoFile(Edit1.Text,S+'head.exe'), то
если УдалитьФайл(Редактировать1.Текст), то
если RenameFile(S+'head.exe',Edit1.Text) тогда
Application.MessageBox('Шифрование файла успешно!','Сообщение',MB_ICONINFORMATION+MB_OK)
еще
начинать
если FileExists(S+'head.exe'), то DeleteFile(S+'head.exe');
Application.MessageBox('Ошибка шифрования файла!','Сообщение',MB_ICONINFORMATION+MB_OK)
конец;
конец;
Среди них ExtractRes — это пользовательская функция, которая используется для извлечения head.exe из файла ресурсов.
Функция ExtractRes(ResType, ResName, ResNewName: String):boolean;
вар
Res: TResourceStream;
начинать
пытаться
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
пытаться
Res.SavetoFile(ResNewName);
Результат:=истина;
окончательно
Рез.Бесплатно;
конец;
кроме
Результат: = ложь;
конец;
конец;
Примечание. Наша функция выше просто добавляет один файл в конец другого файла.
В реальных приложениях его можно изменить, добавив несколько файлов, при условии, что смещение определяется в соответствии с фактическим размером и количеством.
Адрес подойдет. Например, сборщик файлов добавляет две или более программы в файл заголовка.
в. Принципы самораспаковки программ и установщиков те же, но с большим сжатием.
Например, мы можем сослаться на модуль LAH, сжать поток, а затем добавить его, чтобы файл стал меньше.
Просто распакуйте его, прежде чем читать.
Кроме того, пример шифратора EXE в статье все еще имеет много недостатков. Например, пароль фиксирован как.
«790617», после извлечения EXE-файла и его запуска следует дождаться завершения его работы, а затем удалить его и т. д. Читатели могут изменить его самостоятельно.