ストリームとは何ですか?ストリームとは、簡単に言うとオブジェクト指向に基づいた抽象的なデータ処理です。
ツール。ストリームでは、データの読み取り、データの書き込みなど、データを処理するためのいくつかの基本操作が定義されます。
プログラマは、ストリームの他端でのデータの実際のフロー方向を気にせずに、ストリーム上ですべての操作を実行します。流れない
ただし、ファイル、動的メモリ、ネットワーク データ、その他のデータ形式を処理できます。あなたが正しいなら
ストリームの操作は非常に熟練しており、プログラム内でストリームの利便性を利用すると、プログラム作成の効率が大幅に向上します。
以下に、著者は 4 つの例を使用します: EXE ファイル暗号化、電子グリーティング カード、自家製 OICQ、ネットワーク画面
Delphi プログラミングにおける「ストリーム」の使用法を説明するための送信。これらの例のテクニックの一部は、以前は非常にソフトなものでした。
ファイルの秘密は公開されておらず、誰でも無料でコードを直接引用できるようになりました。
「高い建物は地面からそびえ立っています。」 例を分析する前に、まず流れの基本的な概念と概念を理解しましょう。
機能、これらの基本的なことを理解した後でのみ、次のステップに進むことができます。よく理解してください
これらの基本的な方法。もちろん、すでに慣れている場合は、このステップをスキップできます。
1. Delphi のストリームの基本概念と関数宣言
Delphi では、すべてのストリーム オブジェクトの基本クラスは TStream クラスであり、すべてのストリームの共通プロパティを定義します。
と方法。
TStream クラスで定義されるプロパティは次のように導入されます。
1. サイズ: このプロパティは、ストリーム内のデータのサイズをバイト単位で返します。
2. 位置: この属性は、フロー内のアクセス ポインターの位置を制御します。
Tstream には 4 つの仮想メソッドが定義されています。
1. 読み取り: このメソッドはストリームからデータを読み取ります。関数のプロトタイプは次のとおりです。
関数 Read(var Buffer;Count:Longint):Longint;virtual;abstract;
パラメータ Buffer はデータの読み取り時に配置されるバッファ、Count は読み取られるデータのバイト数、
このメソッドの戻り値は、実際に読み取られたバイト数であり、Count で指定された値以下になる可能性があります。
2. Write: このメソッドはデータをストリームに書き込みます。関数のプロトタイプは次のとおりです。
関数 Write(var Buffer;Count:Longint):Longint;virtual;abstract;
パラメーター Buffer はストリームに書き込まれるデータのバッファー、Count はデータの長さ (バイト単位)、
このメソッドの戻り値は、実際にストリームに書き込まれたバイト数です。
3. Seek: このメソッドは、ストリーム内の読み取りポインタの移動を実装します。関数のプロトタイプは次のとおりです。
Function Seek(オフセット:倍長整数;原点:単語):倍長整数;仮想;抽象;
パラメータ Offset はオフセット バイト数で、パラメータ Origin は Offset の実際の意味とその可能な値を示します。
次のように:
soFromBeginning:Offset は、移動後のデータの先頭からのポインタの位置です。このとき、オフセットは
ゼロ以上。
soFromCurrent:Offset は、移動後のポインタと現在のポインタの相対位置です。
soFromEnd:Offset は移動後のデータ先頭からのポインタの位置です。このとき、オフセットは
ゼロ以下。
このメソッドの戻り値は、移動後のポインタの位置です。
4. Setsize: このメソッドはデータのサイズを変更します。関数のプロトタイプは次のとおりです。
関数 Setsize(NewSize:Longint);virtual;
さらに、いくつかの静的メソッドも TStream クラスで定義されています。
1. ReadBuffer: このメソッドの機能は、ストリーム内の現在位置からデータを読み取ることです。関数のプロトタイプは次のとおりです。
PROcedure ReadBuffer(var Buffer;Count:Longint);
パラメータの定義は上記のReadと同じです。注: 読み出したデータのバイト数が読み出し必要なバイト数と異なる場合
数値が異なる場合はEReadError例外が発生します。
2. WriteBuffer: このメソッドの機能は、ストリームの現在位置にデータを書き込むことです。関数のプロトタイプは次のとおりです。
プロシージャ WriteBuffer(var Buffer;Count:Longint);
パラメータの定義は上記の書き込みと同じです。注: 書き込むデータのバイト数が書き込む必要のあるバイト数と異なる場合
数値が異なる場合はEWriteError例外が発生します。
3. CopyFrom: このメソッドは、他のストリームからデータ ストリームをコピーするために使用されます。関数のプロトタイプは次のとおりです。
関数 CopyFrom(ソース:TStream;カウント:倍長整数):倍長整数;
パラメータ Source はデータを提供するストリームで、Count はコピーされたデータ バイト数です。 Count が 0 より大きい場合、
CopyFrom は、Count が 0 の場合、Source パラメーターの現在位置から Count バイトのデータをコピーします。
CopyFrom は、Source パラメーターの Position プロパティを 0 に設定し、Source のすべてのデータをコピーします。
TStream には他にも派生クラスがあり、最もよく使用されるのは TFileStream クラスです。 TFileStream の使用
クラスを使用してファイルにアクセスするには、まずインスタンスを作成する必要があります。声明は次のとおりです。
コンストラクター Create(const ファイル名:文字列;モード:Word);
Filename はファイル名 (パスを含む)、パラメータ Mode はファイルを開く方法 (ファイルを開く方法を含む) です。
オープン モードと共有モード、それらの可能な値と意味は次のとおりです。
オープンモード:
fmCreate: 指定されたファイル名でファイルを作成するか、ファイルが既に存在する場合はそのファイルを開きます。
fmOpenRead: 指定されたファイルを読み取り専用モードで開きます
fmOpenWrite: 指定されたファイルを書き込み専用モードで開きます
fmOpenReadWrite: 指定されたファイルを書き込み用に開きます
共有モード:
fmShareCompat: 共有モードは FCB と互換性があります
fmShareExclusive: 他のプログラムがファイルを開くことをいかなる方法でも許可しません
fmShareDenyWrite: 他のプログラムが書き込みのためにファイルを開くことを許可しません
fmShareDenyRead: 他のプログラムが読み取りモードでファイルを開くことを許可しません
fmShareDenyNone: 他のプログラムがどのような方法でもファイルを開くことができます
TStream には派生クラス TMemoryStream もあり、実際のアプリケーションでよく使用されます。
非常に頻繁に。これはメモリ ストリームと呼ばれ、メモリ内にストリーム オブジェクトを作成することを意味します。その基本的なメソッドと機能は次のとおりです。
同上。
さて、上記の基礎が整ったら、プログラミングの旅を始めることができます。
-------------------------------------------------- ------------------------
2. 実用的なアプリケーション 1: ストリームを使用して EXE ファイル暗号化プログラム、バンドル、自己解凍ファイル、インストール プログラムを作成する
まず、EXE ファイル暗号化プログラムの作成方法について説明します。
EXE ファイル暗号化の原理: 2 つのファイルを作成し、1 つはリソースをもう 1 つの EXE ファイルに追加するために使用されます。
内部ではアドイン プログラムと呼ばれます。追加される別の EXE ファイルはヘッダー ファイルと呼ばれます。このプログラムの機能は、
それ自体に追加されたファイルを読み取ります。
Windows の EXE ファイルの構造は比較的複雑で、チェックサムが変更されているプログラムもあります。
後で、彼らはウイルスに感染していると考え、ウイルスの実行を拒否するでしょう。そこで、このファイルをプログラムに追加します。
これにより、元のファイル構造は変更されません。まず add 関数を作成しましょう。この関数の機能は追加することです。
1 つのファイルがストリームとして別のファイルの末尾に追加されます。機能は次のとおりです。
関数 Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
変数
ターゲット、ソース:TFileStream;
MyFileSize:整数;
始める
試す
Source:=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 は、追加するターゲット ファイルです。たとえば、a.exe を次のように追加します。
b.exe では次のことができます: Cjt_AddtoFile('a.exe',b.exe'); 追加が成功した場合は True を返し、それ以外の場合は True を返します。
falseを返します。
上記の関数に基づいて、逆の読み取り関数を作成できます。
関数 Cjt_LoadFromFile(SourceFile,TargetFile:string):Boolean;
変数
ソース:TFileStream;
ターゲット:TMemoryStream;
MyFileSize:整数;
始める
試す
ターゲット:=TMemoryStream.Create;
Source:=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);// ファイルに保存
ついに
ターゲット。無料。
出典.無料;
終わり;
を除外する
結果:=false;
出口;
終わり;
結果:= true;
終わり;
パラメータSourceFileは追加したファイルのファイル名、パラメータTargetFileは取り出したファイル名です。
ファイルの後に保存するターゲットファイル名。たとえば、b.exe では Cjt_LoadFromFile('b.exe','a.txt');
ファイルを取り出し、.txt として保存します。抽出が成功した場合は True を返し、そうでない場合は False を返します。
Delphi を開き、新しいプロジェクトを作成し、編集コントロール Edit1 と 2 つのボタンをウィンドウに配置します。
ボタン1とボタン2。ボタンの Caption プロパティはそれぞれ「OK」と「Cancel」に設定されます。存在する
Button1 の Click イベントにコードを記述します。
var S: 文字列;
始める
S:=ChangeFileExt(application.ExeName,'.Cjt');
Edit1.Text='790617' の場合、
始める
Cjt_LoadFromFile(アプリケーション.Exe名,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 で、Delphi の BIN ディレクトリにコピーして実行します。
Dos コマンド Brcc32.exe head.rc は head.res ファイルを生成します。このファイルが必要です。
リソース ファイルは最初に保存してください。
ヘッダー ファイルが作成されました。アドイン プログラムを作成しましょう。
新しいプロジェクトを作成し、次のコントロールを配置します: 1 つの Edit、1 つの Opendialog、および 2 つの Button1
キャプションのプロパティはそれぞれ「ファイルの選択」と「暗号化」に設定されます。
ソース プログラムに {$R head.res} という文を追加し、head.res ファイルをプログラムの現在のディレクトリにコピーします。
このようにして、先ほどのhead.exeがプログラムと一緒にコンパイルされます。
Button1 の Cilck イベントにコードを記述します。
OpenDialog1.Execute の場合、Edit1.Text:=OpenDialog1.FileName;
Button2 の Cilck イベントにコードを記述します。
var S:文字列;
始める
S:=ExtractFilePath(Edit1.Text);
if ExtractRes('exefile','head',S+'head.exe') then
if Cjt_AddtoFile(Edit1.Text,S+'head.exe') then
if DeleteFile(Edit1.Text) then
if RenameFile(S+'head.exe',Edit1.Text) then
Application.MessageBox('ファイルの暗号化が成功しました!','メッセージ',MB_ICONINFORMATION+MB_OK)
それ以外
始める
if FileExists(S+'head.exe') then DeleteFile(S+'head.exe');
Application.MessageBox('ファイルの暗号化に失敗しました!','メッセージ',MB_ICONINFORMATION+MB_OK)
終わり;
終わり;
このうち、ExtractRes はカスタム関数で、リソース ファイルから head.exe を抽出するために使用されます。
関数 ExtractRes(ResType, ResName, ResNewName : String):boolean;
変数
解像度 : TResourceStream;
始める
試す
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
試す
Res.SavetoFile(ResNewName);
結果:= true;
ついに
解像度無料。
終わり;
を除外する
結果:=false;
終わり;
終わり;
注: 上記の関数は、あるファイルを別のファイルの末尾に追加するだけです。
実際のアプリケーションでは、実際のサイズと数に従ってオフセットが定義されている限り、複数のファイルを追加するように変更できます。
住所でも大丈夫です。たとえば、ファイル バンドラーは 2 つ以上のプログラムをヘッダー ファイルに追加します。
で。自己解凍プログラムとインストーラーの原理は同じですが、圧縮率が高くなります。
たとえば、LAH ユニットを参照し、ストリームを圧縮してから追加すると、ファイルが小さくなります。
読み出す前に解凍してください。
さらに、記事内の EXE 暗号化プログラムの例には、パスワードが次のように固定されているなど、まだ多くの不完全な点があります。
「790617」は、EXEを取り出して実行した後、実行が完了するまで待ってから削除するなどしてください。読者は自分で変更できます。