ما هو الدفق؟ الدفق، ببساطة، عبارة عن بيانات معالجة مجردة تعتمد على الكائنات الموجهة
أدوات. يتم في الدفق تحديد بعض العمليات الأساسية لمعالجة البيانات، مثل قراءة البيانات وكتابة البيانات وما إلى ذلك.
يقوم المبرمج بتنفيذ جميع العمليات على الدفق دون الاهتمام باتجاه التدفق الفعلي للبيانات في الطرف الآخر من الدفق. لا يتدفق
ولكن يمكنه معالجة الملفات والذاكرة الديناميكية وبيانات الشبكة ونماذج البيانات الأخرى. إذا كنت على حق
يعد تشغيل التدفقات أمرًا بارعًا للغاية. سيؤدي استخدام راحة التدفقات في البرامج إلى تحسين كفاءة كتابة البرامج بشكل كبير.
أدناه، يستخدم المؤلف أربعة أمثلة: تشفير ملفات EXE، وبطاقة التهنئة الإلكترونية، وOICQ محلي الصنع، وشاشة الشبكة
نقل لتوضيح استخدام "الدفق" في برمجة دلفي. بعض التقنيات في هذه الأمثلة كانت لينة جدًا
سر الملف ليس مفتوحًا للعامة، والآن يمكن للجميع اقتباس الكود مباشرة مجانًا.
"المباني الشاهقة ترتفع من الأرض." قبل تحليل الأمثلة، دعونا أولاً نفهم المفاهيم والمفاهيم الأساسية للتدفق.
الوظائف، فقط بعد فهم هذه الأشياء الأساسية يمكننا الانتقال إلى الخطوة التالية. يرجى فهم بعناية
هذه الأساليب الأساسية. وبطبيعة الحال، إذا كنت على دراية بها بالفعل، يمكنك تخطي هذه الخطوة.
1. المفاهيم الأساسية وإعلانات الوظائف للتدفقات في دلفي
في دلفي، الفئة الأساسية لجميع كائنات التدفق هي فئة TStream، التي تحدد الخصائص المشتركة لجميع التدفقات.
والأساليب.
يتم تقديم الخصائص المحددة في فئة TStream على النحو التالي:
1. الحجم: تُرجع هذه الخاصية حجم البيانات الموجودة في الدفق بالبايت.
2. الموضع: تتحكم هذه السمة في موضع مؤشر الوصول في التدفق.
هناك أربع طرق افتراضية محددة في Tstream:
1. القراءة: تقوم هذه الطريقة بقراءة البيانات من الدفق. النموذج الأولي للوظيفة هو:
قراءة الدالة (var Buffer;Count:Longint):Longint;virtual;abstract;
المعلمة Buffer هي المخزن المؤقت الذي يتم وضعه عند قراءة البيانات، Count هو عدد بايتات البيانات المراد قراءتها،
القيمة المرجعة لهذه الطريقة هي العدد الفعلي للبايتات المقروءة، والتي يمكن أن تكون أقل من أو تساوي القيمة المحددة في العدد.
2. الكتابة: تقوم هذه الطريقة بكتابة البيانات في الدفق. النموذج الأولي للوظيفة هو:
كتابة الوظيفة (var Buffer;Count:Longint):Longint;virtual;abstract;
المعلمة Buffer هي المخزن المؤقت للبيانات المراد كتابتها في الدفق، Count هو طول البيانات بالبايت،
القيمة المرجعة لهذه الطريقة هي عدد البايتات المكتوبة بالفعل في الدفق.
3. البحث: تنفذ هذه الطريقة حركة مؤشر القراءة في الدفق. النموذج الأولي للوظيفة هو:
البحث عن الوظيفة (الإزاحة: Longint؛ الأصل: Word): Longint؛ Virtual؛ Abstract؛
المعلمة Offset هي عدد بايتات الإزاحة، وتشير المعلمة Origin إلى المعنى الفعلي للإزاحة وقيمها المحتملة.
على النحو التالي:
soFromBeginning:Offset هو موضع المؤشر من بداية البيانات بعد الحركة. في هذا الوقت يجب الإزاحة
أكبر من أو يساوي الصفر.
soFromCurrent:Offset هو الموضع النسبي للمؤشر بعد الحركة والمؤشر الحالي.
soFromEnd:Offset هو موضع المؤشر من بداية البيانات بعد الحركة. في هذا الوقت يجب الإزاحة
أقل من أو يساوي الصفر.
القيمة المرجعة لهذه الطريقة هي موضع المؤشر بعد الحركة.
4. حجم المجموعة: تعمل هذه الطريقة على تغيير حجم البيانات. النموذج الأولي للوظيفة هو:
حجم مجموعة الوظائف (NewSize: Longint)؛
بالإضافة إلى ذلك، يتم تعريف العديد من الطرق الثابتة أيضًا في فئة TStream:
1. ReadBuffer: وظيفة هذه الطريقة هي قراءة البيانات من الموضع الحالي في الدفق. النموذج الأولي للوظيفة هو:
PROcedure ReadBuffer(var Buffer;Count:Longint);
تعريف المعلمات هو نفس ما ورد أعلاه. ملاحظة: عندما يختلف عدد بايتات البيانات المقروءة عن عدد البايتات التي يجب قراءتها
عندما تكون الأرقام مختلفة، سيتم إنشاء استثناء EReadError.
2. WriteBuffer: وظيفة هذه الطريقة هي كتابة البيانات إلى الدفق في الموضع الحالي. النموذج الأولي للوظيفة هو:
الإجراء WriteBuffer(var Buffer;Count:Longint);
تعريف المعلمات هو نفس ما ورد أعلاه. ملاحظة: عندما يختلف عدد بايتات البيانات المكتوبة عن عدد البايتات التي يجب كتابتها
عندما تكون الأرقام مختلفة، سيتم إنشاء استثناء EWriteError.
3. CopyFrom: تُستخدم هذه الطريقة لنسخ تدفقات البيانات من التدفقات الأخرى. النموذج الأولي للوظيفة هو:
وظيفة CopyFrom(Source:TStream;Count:Longint):Longint;
المعلمة المصدر هي الدفق الذي يوفر البيانات، والعدد هو عدد بايتات البيانات المنسوخة. عندما يكون العدد أكبر من 0،
CopyFrom ينسخ عدد بايتات البيانات من الموضع الحالي لمعلمة المصدر عندما يساوي العدد 0،
يقوم CopyFrom بتعيين خاصية الموضع لمعلمة المصدر على 0، ثم ينسخ كافة بيانات المصدر؛
لدى TStream فئات مشتقة أخرى، وأكثرها استخدامًا هي فئة TFileStream. باستخدام تيفيلستريم
للوصول إلى الملفات باستخدام فئة، يجب عليك أولاً إنشاء مثيل. البيان هو كما يلي:
إنشاء المنشئ (اسم ملف const: سلسلة؛ الوضع: Word)؛
اسم الملف هو اسم الملف (بما في ذلك المسار)، والمعلمة Mode هي طريقة فتح الملف، والتي تتضمن كيفية فتح الملف.
الوضع المفتوح والوضع المشترك، قيمهما ومعانيهما المحتملة هي كما يلي:
الوضع المفتوح:
fmCreate: قم بإنشاء ملف باسم الملف المحدد، أو افتح الملف إذا كان موجودًا بالفعل.
fmOpenRead: فتح الملف المحدد في وضع القراءة فقط
fmOpenWrite: فتح الملف المحدد في وضع الكتابة فقط
fmOpenReadWrite: فتح الملف المحدد للكتابة
وضع المشاركة:
fmShareCompat: وضع المشاركة متوافق مع FCBs
fmShareExclusive: لا تسمح للبرامج الأخرى بفتح الملف بأي شكل من الأشكال
fmShareDenyWrite: لا تسمح للبرامج الأخرى بفتح الملف للكتابة
fmShareDenyRead: لا تسمح للبرامج الأخرى بفتح الملف في وضع القراءة
fmShareDenyNone: يمكن للبرامج الأخرى فتح الملف بأي طريقة
لدى TStream أيضًا فئة مشتقة من TMemoryStream، والتي يتم استخدامها كثيرًا في التطبيقات الفعلية.
في كثير من الأحيان. يطلق عليه دفق الذاكرة، وهو ما يعني إنشاء كائن دفق في الذاكرة. تتبع أساليبها ووظائفها الأساسية
نفس ما ورد أعلاه.
حسنًا، مع وضع الأساس المذكور أعلاه، يمكننا أن نبدأ رحلة البرمجة الخاصة بنا.
-------------------------------------------------- --------------------------
2. التطبيق العملي الأول: استخدام التدفقات لإنشاء برامج تشفير ملفات EXE والحزم وملفات الاستخراج الذاتي وبرامج التثبيت
لنتحدث أولاً عن كيفية إنشاء برنامج تشفير لملفات EXE.
مبدأ تشفير ملفات EXE: إنشاء ملفين، يستخدم أحدهما لإضافة الموارد إلى ملف EXE الآخر
في الداخل، يطلق عليه برنامج الوظيفة الإضافية. يسمى ملف EXE الآخر الذي تتم إضافته بملف الرأس. وظيفة هذا البرنامج هي
قراءة الملفات المضافة إلى نفسه.
تكون بنية ملفات EXE في Windows معقدة نسبيًا. تحتوي بعض البرامج أيضًا على مجاميع اختبارية
لاحقًا، سيعتقدون أنهم مصابون بالفيروس ويرفضون تنفيذه. لذلك نقوم بإضافة الملف إلى برنامجنا،
لن يؤدي هذا إلى تغيير بنية الملف الأصلي. لنكتب أولاً وظيفة إضافة. وظيفة هذه الوظيفة هي الإضافة
يتم إلحاق ملف واحد بنهاية ملف آخر كدفق. الوظيفة هي كما يلي:
الوظيفة Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
فار
الهدف، المصدر: TFileStream؛
MyFileSize:integer;
يبدأ
يحاول
المصدر:=TFileStream.Create(SourceFile,fmOpenRead أو fmShareExclusive);
Target:=TFileStream.Create(TargetFile,fmOpenWrite أو fmShareExclusive);
يحاول
Target.Seek(0,soFromEnd);// أضف الموارد إلى النهاية
Target.CopyFrom(Source,0);
MyFileSize:=Source.Size+Sizeof(MyFileSize);// احسب حجم المورد واكتبه في نهاية العملية المساعدة
Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));
أخيراً
Target.Free;
المصدر.مجاني؛
نهاية؛
يستثني
النتيجة:=خطأ؛
مخرج؛
نهاية؛
النتيجة:=صحيح؛
نهاية؛
مع الأساس المذكور أعلاه، يجب أن نفهم هذه الوظيفة بسهولة. حيث توجد المعلمة SourceFile
الملف المراد إضافته، المعلمة TargetFile هي الملف الهدف المراد إضافته. على سبيل المثال، قم بإضافة ملف a.exe إلى
في b.exe، يمكنك: Cjt_AddtoFile('a.exe',b.exe'); إذا كانت الإضافة ناجحة، فارجع True بخلاف ذلك
العودة كاذبة.
بناءً على الوظيفة المذكورة أعلاه يمكننا كتابة وظيفة القراءة المعاكسة:
الوظيفة Cjt_LoadFromFile(SourceFile,TargetFile:string):Boolean;
فار
المصدر:TFileStream;
الهدف: TMemoryStream؛
MyFileSize:integer;
يبدأ
يحاول
الهدف:=TMemoryStream.Create;
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone);
يحاول
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));// قراءة حجم المورد
Source.Seek(-MyFileSize,soFromEnd);// حدد موقع المورد
Target.CopyFrom(Source,MyFileSize-sizeof(MyFileSize));//إزالة الموارد
Target.SaveToFile(TargetFile);//حفظ في الملف
أخيراً
Target.Free;
المصدر.مجاني؛
نهاية؛
يستثني
النتيجة:=خطأ؛
مخرج؛
نهاية؛
النتيجة:=صحيح؛
نهاية؛
المعلمة SourceFile هي اسم الملف المضاف، والمعلمة TargetFile هي اسم الملف الذي تم إزالته.
اسم الملف الهدف المراد حفظه بعد الملف. على سبيل المثال، Cjt_LoadFromFile('b.exe','a.txt'); في b.exe
أخرج الملف واحفظه بصيغة a.txt. إذا نجح الاستخراج، فسيتم إرجاع True وإلا فسيتم إرجاع False.
افتح دلفي، وأنشئ مشروعًا جديدًا، ثم ضع عنصر التحكم Edit1 وزرين في النافذة:
Button1 و Button2. تم تعيين خاصية التسمية التوضيحية للزر على "موافق" و"إلغاء" على التوالي. يخرج
اكتب الكود في حدث Click لـ Button1:
فار S: سلسلة؛
يبدأ
S:=ChangeFileExt(application.ExeName,'.Cjt');
إذا Edit1.Text='790617' إذن
يبدأ
Cjt_LoadFromFile(Application.ExeName,S);
{أخرج الملف واحفظه في المسار الحالي وأطلق عليه اسم "Original file.Cjt"}
Winexec(pchar(S),SW_Show);{تشغيل "الملف الأصلي.Cjt"}
التطبيق.إنهاء؛{الخروج من البرنامج}
نهاية
آخر
Application.MessageBox('كلمة المرور غير صحيحة، يرجى إعادة الإدخال!'، 'كلمة المرور غير صحيحة'، MB_ICONERROR+MB_OK);
قم بتجميع هذا البرنامج وإعادة تسمية ملف EXE إلى head.exe. إنشاء ملف نصي جديد head.rc،
المحتوى هو: head exefile head.exe، ثم انسخها إلى دليل BIN الخاص بدلفي وقم بالتنفيذ
سيقوم أمر Dos Brcc32.exe head.rc بإنشاء ملف head.res. هذا الملف هو ما نريده
ملفات الموارد، احتفظ بها أولاً.
تم إنشاء ملف الرأس الخاص بنا، فلنقم بإنشاء برنامج الوظيفة الإضافية.
أنشئ مشروعًا جديدًا وضع عناصر التحكم التالية: واحد تحرير، وواحد 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') ثم
إذا حذف ملف (Edit1.Text) ثم
إذا RenameFile(S+'head.exe',Edit1.Text) ثم
Application.MessageBox('تم تشفير الملف بنجاح!','رسالة',MB_ICONINFORMATION+MB_OK)
آخر
يبدأ
إذا كان FileExists(S+'head.exe') ثم حذف File(S+'head.exe');
Application.MessageBox('فشل تشفير الملف!','رسالة',MB_ICONINFORMATION+MB_OK)
نهاية؛
نهاية؛
من بينها، ExtractRes هي وظيفة مخصصة تُستخدم لاستخراج head.exe من ملف المورد.
الدالة ExtractRes(ResType, ResName, ResNewName: String): boolean;
فار
الدقة: تريسورسستريم؛
يبدأ
يحاول
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
يحاول
Res.SavetoFile(ResNewName);
النتيجة:=صحيح؛
أخيراً
الدقة.مجاني؛
نهاية؛
يستثني
النتيجة:=خطأ؛
نهاية؛
نهاية؛
ملحوظة: تقوم وظيفتنا أعلاه ببساطة بإلحاق ملف واحد بنهاية ملف آخر.
في التطبيقات الفعلية، يمكن تغييره لإضافة ملفات متعددة، طالما تم تحديد الإزاحة وفقًا للحجم والرقم الفعليين
العنوان سيفي بالغرض. على سبيل المثال، يقوم مجمّع الملفات بإضافة برنامجين أو أكثر إلى ملف الرأس.
في. مبادئ برامج الاستخراج الذاتي والمثبتات هي نفسها، ولكن مع المزيد من الضغط.
على سبيل المثال، يمكننا الرجوع إلى وحدة LAH، وضغط الدفق ثم إضافتها، بحيث يصبح الملف أصغر.
فقط قم بفك الضغط عنها قبل قراءتها.
بالإضافة إلى ذلك، لا يزال مثال تشفير EXE الموجود في المقالة يحتوي على العديد من العيوب، على سبيل المثال، تم إصلاح كلمة المرور كـ
"790617"، بعد إخراج ملف EXE وتشغيله، عليك الانتظار حتى انتهاء تشغيله ثم حذفه، وما إلى ذلك. ويمكن للقراء تعديله بأنفسهم.