Apa itu aliran? Stream, sederhananya, adalah pemrosesan data abstrak berdasarkan berorientasi objek
peralatan. Di aliran, beberapa operasi dasar untuk memproses data didefinisikan, seperti membaca data, menulis data, dll.
Pemrogram melakukan semua operasi pada aliran tanpa mempedulikan arah aliran sebenarnya dari data di ujung aliran yang lain. Mengalir tidak
Tapi itu bisa memproses file, memori dinamis, data jaringan dan bentuk data lainnya. jika kamu benar
Pengoperasian stream sangat mahir. Menggunakan kenyamanan stream dalam program akan sangat meningkatkan efisiensi penulisan program.
Di bawah ini, penulis menggunakan empat contoh: enkripsi file EXE, kartu ucapan elektronik, OICQ buatan sendiri, dan layar jaringan
Transmisi untuk menggambarkan penggunaan "stream" dalam pemrograman Delphi. Beberapa teknik dalam contoh ini dulunya sangat lembut
Rahasia file tersebut tidak dibuka untuk umum, dan kini semua orang bisa langsung mengutip kodenya secara gratis.
“Bangunan tinggi menjulang dari permukaan tanah.” Sebelum menganalisis contohnya, mari kita pahami dulu konsep dasar dan konsep aliran.
Fungsinya, baru setelah memahami hal-hal dasar tersebut kita bisa melanjutkan ke langkah selanjutnya. Harap dipahami dengan cermat
metode dasar ini. Tentu saja, jika Anda sudah familiar dengannya, Anda bisa melewati langkah ini.
1. Konsep dasar dan deklarasi fungsi stream di Delphi
Di Delphi, kelas dasar dari semua objek aliran adalah kelas TStream, yang mendefinisikan properti umum dari semua aliran.
dan metode.
Properti yang didefinisikan dalam kelas TStream diperkenalkan sebagai berikut:
1. Ukuran: Properti ini mengembalikan ukuran data dalam aliran dalam byte.
2. Posisi: Atribut ini mengontrol posisi penunjuk akses dalam aliran.
Ada empat metode virtual yang ditentukan di Tstream:
1. Baca: Metode ini membaca data dari aliran. Prototipe fungsinya adalah:
Fungsi Baca(var Buffer;Hitung:Longint):Longint;virtual;abstrak;
Parameter Buffer adalah buffer yang ditempatkan ketika membaca data, Count adalah jumlah byte data yang akan dibaca,
Nilai yang dikembalikan metode ini adalah jumlah byte sebenarnya yang dibaca, yang bisa kurang dari atau sama dengan nilai yang ditentukan dalam Hitungan.
2. Tulis: Metode ini menulis data ke dalam aliran. Prototipe fungsinya adalah:
Fungsi Tulis(var Buffer;Hitungan:Longint):Longint;virtual;abstrak;
Parameter Buffer adalah buffer data yang akan ditulis ke dalam stream, Count adalah panjang data dalam byte,
Nilai kembalian dari metode ini adalah jumlah byte yang sebenarnya ditulis ke aliran.
3. Carilah: Metode ini mengimplementasikan pergerakan penunjuk baca di aliran. Prototipe fungsinya adalah:
Fungsi Mencari(Offset:Longint;Asal:Word):Longint;virtual;abstrak;
Parameter Offset adalah jumlah byte offset, dan parameter Asal menunjukkan arti sebenarnya dari Offset dan kemungkinan nilainya.
sebagai berikut:
soFromBeginning:Offset adalah posisi penunjuk dari awal data setelah pergerakan. Saat ini Offset harus
Lebih besar dari atau sama dengan nol.
soFromCurrent:Offset adalah posisi relatif penunjuk setelah pergerakan dan penunjuk saat ini.
soFromEnd:Offset adalah posisi penunjuk dari awal data setelah pergerakan. Saat ini Offset harus
Kurang dari atau sama dengan nol.
Nilai kembalian metode ini adalah posisi penunjuk setelah pergerakan.
4. Setsize: Metode ini mengubah ukuran data. Prototipe fungsinya adalah:
Fungsi Setsize(Ukuran Baru:Longint);virtual;
Selain itu, beberapa metode statis juga didefinisikan di kelas TStream:
1. ReadBuffer: Fungsi metode ini adalah membaca data dari posisi saat ini di aliran. Prototipe fungsinya adalah:
Prosedur ReadBuffer(var Buffer;Hitungan:Longint);
Definisi parameter sama dengan Baca di atas. Catatan: Bila jumlah byte data yang dibaca berbeda dengan byte yang perlu dibaca
Jika angkanya berbeda, pengecualian EReadError akan dihasilkan.
2. WriteBuffer: Fungsi metode ini adalah untuk menulis data ke aliran pada posisi saat ini. Prototipe fungsinya adalah:
Prosedur WriteBuffer(var Buffer;Hitungan:Longint);
Definisi parameter sama dengan Tulis di atas. Catatan: Bila jumlah byte data yang ditulis berbeda dengan byte yang perlu ditulis
Jika angkanya berbeda, pengecualian EWriteError akan dihasilkan.
3. CopyFrom: Metode ini digunakan untuk menyalin aliran data dari aliran lain. Prototipe fungsinya adalah:
Fungsi CopyFrom(Sumber:TStream;Hitungan:Longint):Longint;
Parameter Sumber adalah aliran yang menyediakan data, dan Hitungan adalah jumlah byte data yang disalin. Ketika Hitungan lebih besar dari 0,
CopyFrom menyalin Hitung byte data dari posisi parameter Sumber saat ini; ketika Hitung sama dengan 0,
CopyFrom menyetel properti Posisi dari parameter Sumber ke 0, lalu menyalin semua data Sumber;
TStream memiliki kelas turunan lainnya, yang paling umum digunakan adalah kelas TFileStream. Menggunakan TFileStream
Untuk mengakses file menggunakan kelas, Anda harus membuat instance terlebih dahulu. Pernyataannya adalah sebagai berikut:
konstruktor Buat(const Nama file:string;Mode:Word);
Nama file adalah nama file (termasuk path), dan parameter Mode adalah cara membuka file, yang mencakup cara membuka file.
Mode terbuka dan mode bersama, kemungkinan nilai dan maknanya adalah sebagai berikut:
Modus terbuka:
fmCreate: Buat file dengan nama file yang ditentukan, atau buka file jika sudah ada.
fmOpenRead: Buka file tertentu dalam mode read-only
fmOpenWrite: Buka file tertentu dalam mode tulis saja
fmOpenReadWrite: Membuka file yang ditentukan untuk menulis
Modus berbagi:
fmShareCompat: Mode berbagi kompatibel dengan FCB
fmShareExclusive: Jangan izinkan program lain membuka file dengan cara apa pun
fmShareDenyWrite: Jangan izinkan program lain membuka file untuk ditulis
fmShareDenyRead: Jangan izinkan program lain membuka file dalam mode baca
fmShareDenyNone: Program lain dapat membuka file dengan cara apa pun
TStream juga memiliki kelas turunan TMemoryStream, yang sangat sering digunakan dalam aplikasi sebenarnya.
Sangat sering. Ini disebut aliran memori, yang berarti membuat objek aliran di memori. Metode dan fungsi dasarnya mengikuti
Sama seperti di atas.
Nah, dengan landasan di atas, kita bisa memulai perjalanan pemrograman kita.
--------------------------------------------------- --------------------------
2. Aplikasi praktis pertama: menggunakan aliran untuk membuat enkripsi file EXE, bundel, file self-extracting dan program instalasi
Pertama mari kita bicara tentang cara membuat enkripsi file EXE.
Prinsip enkripsi file EXE: membuat dua file, satu digunakan untuk menambahkan sumber daya ke file EXE lainnya
Di dalamnya, ini disebut program tambahan. File EXE lain yang ditambahkan disebut file header. Fungsi dari program ini adalah
Baca file yang ditambahkan ke dirinya sendiri.
Struktur file EXE di Windows relatif rumit. Beberapa program juga memiliki checksum jika Anda menemukannya telah diubah
Nantinya, mereka akan mengira dirinya tertular virus tersebut dan menolak untuk mengeksekusinya. Jadi kami menambahkan file tersebut ke program kami,
Ini tidak akan mengubah struktur file asli. Mari kita tulis dulu fungsi penjumlahan. Fungsi dari fungsi ini adalah untuk menjumlahkan
Satu file ditambahkan ke akhir file lain sebagai aliran. Fungsinya adalah sebagai berikut:
Fungsi Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
var
Target,Sumber:TFileStream;
Ukuran File Saya: bilangan bulat;
mulai
mencoba
Sumber:=TFileStream.Create(SourceFile,fmOpenRead atau fmShareExclusive);
Target:=TFileStream.Create(TargetFile,fmOpenWrite atau fmShareExclusive);
mencoba
Target.Seek(0,soFromEnd);//Tambahkan sumber daya sampai akhir
Target.CopyFrom(Sumber,0);
MyFileSize:=Source.Size+Sizeof(MyFileSize);//Hitung ukuran sumber daya dan tuliskan di akhir proses tambahan
Target.WriteBuffer(Ukuran File Saya,ukuran(Ukuran File Saya));
Akhirnya
Target.Gratis;
Sumber.Gratis;
akhir;
kecuali
Hasil:=Salah;
KELUAR;
akhir;
Hasil:=Benar;
akhir;
Dengan landasan di atas, kita akan dengan mudah memahami fungsi ini. di mana parameter SourceFile berada
File yang akan ditambahkan, parameter TargetFile adalah file target yang akan ditambahkan. Misalnya, tambahkan a.exe ke
Di b.exe Anda dapat: Cjt_AddtoFile('a.exe',b.exe'); jika penambahan berhasil, kembalikan True jika tidak
Kembalikan salah.
Berdasarkan fungsi di atas kita dapat menulis fungsi baca sebaliknya:
Fungsi Cjt_LoadFromFile(SourceFile,TargetFile:string):Boolean;
var
Sumber: TFileStream;
Target:TMemoryStream;
Ukuran File Saya: bilangan bulat;
mulai
mencoba
Target:=TMemoryStream.Buat;
Sumber:=TFileStream.Create(SourceFile,fmOpenRead atau fmShareDenyNone);
mencoba
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//Baca ukuran sumber daya
Source.Seek(-MyFileSize,soFromEnd);//Temukan lokasi sumber daya
Target.CopyFrom(Source,MyFileSize-sizeof(MyFileSize));//Hapus sumber daya
Target.SaveToFile(TargetFile);//Simpan ke file
Akhirnya
Target.Gratis;
Sumber.Gratis;
akhir;
kecuali
Hasil:=salah;
KELUAR;
akhir;
Hasil:=benar;
akhir;
Parameter SourceFile adalah nama file dari file yang ditambahkan, dan parameter TargetFile adalah nama file yang dikeluarkan.
Nama file target yang akan disimpan setelah file. Misalnya, Cjt_LoadFromFile('b.exe','a.txt'); di b.exe
Keluarkan file dan simpan sebagai a.txt. Jika ekstraksi berhasil, ia mengembalikan True jika tidak, ia mengembalikan False.
Buka Delphi, buat proyek baru, dan letakkan kontrol Edit Edit1 dan dua Tombol di jendela:
Tombol1 dan Tombol2. Properti Caption Button masing-masing disetel ke "OK" dan "Cancel". ada
Tulis kode di acara Klik pada Button1:
var S: tali;
mulai
S:=ChangeFileExt(application.ExeName,'.Cjt');
jika Edit1.Teks='790617' lalu
mulai
Cjt_LoadFromFile(Aplikasi.ExeName,S);
{Keluarkan file dan simpan di jalur saat ini dan beri nama "file asli.Cjt"}
Winexec(pchar(S),SW_Show);{Jalankan "file asli.Cjt"}
Aplikasi.Hentikan;{Keluar dari program}
akhir
kalau tidak
Application.MessageBox('Kata Sandi salah, silakan masukkan kembali!', 'Kata Sandi salah', MB_ICONERROR+MB_OK);
Kompilasi program ini dan ganti nama file EXE menjadi head.exe. Buat file teks baru head.rc,
Isinya adalah: head exefile head.exe, lalu salin ke direktori BIN Delphi dan jalankan
Perintah Dos Brcc32.exe head.rc akan menghasilkan file head.res. File inilah yang kita inginkan
File sumber daya, simpan dulu.
File header kita sudah dibuat, mari kita buat program add-innya.
Buat proyek baru dan letakkan kontrol berikut: satu Edit, satu Opendialog, dan dua Button1
Properti Caption masing-masing diatur ke "Pilih File" dan "Terenkripsi".
Tambahkan kalimat di program sumber: {$R head.res} dan salin file head.res ke direktori program saat ini.
Dengan cara ini, head.exe yang tadi dikompilasi bersama dengan program.
Tulis kode di acara Cilck Button1:
jika OpenDialog1.Execute lalu Edit1.Text:=OpenDialog1.FileName;
Tulis kode di acara Cilck Button2:
var S:String;
mulai
S:=ExtractFilePath(Edit1.Teks);
jika ExtractRes('exefile','head',S+'head.exe') lalu
jika Cjt_AddtoFile(Edit1.Text,S+'head.exe') lalu
jika DeleteFile(Edit1.Teks) lalu
jika Ganti NamaFile(S+'head.exe',Edit1.Teks) lalu
Application.MessageBox('Enkripsi file berhasil!','Pesan',MB_ICONINFORMATION+MB_OK)
kalau tidak
mulai
jika FileExists(S+'head.exe') maka DeleteFile(S+'head.exe');
Application.MessageBox('Enkripsi file gagal!','Pesan',MB_ICONINFORMATION+MB_OK)
akhir;
akhir;
Diantaranya, ExtractRes adalah fungsi khusus yang digunakan untuk mengekstrak head.exe dari file sumber daya.
Fungsi ExtractRes(ResType, ResName, ResNewName : String):boolean;
var
Perihal : TResourceStream;
mulai
mencoba
Res := TResourceStream.Create(Petunjuk, Ganti Nama, Pchar(ResType));
mencoba
Res.SavetoFile(ResNewName);
Hasil:=benar;
Akhirnya
Res.Gratis;
akhir;
kecuali
Hasil:=salah;
akhir;
akhir;
Catatan: Fungsi kami di atas hanya menambahkan satu file ke akhir file lainnya.
Dalam aplikasi sebenarnya, ini dapat diubah untuk menambahkan banyak file, selama offset ditentukan sesuai dengan ukuran dan jumlah sebenarnya
Alamatnya cukup. Misalnya, file bundler menambahkan dua atau lebih program ke file header.
di dalam. Prinsip program self-extracting dan installernya sama, tetapi dengan kompresi yang lebih besar.
Misalnya kita bisa mereferensikan unit LAH, mengompres alirannya lalu menambahkannya, sehingga file menjadi lebih kecil.
Cukup dekompresi sebelum membacanya.
Selain itu, contoh encryptor EXE pada artikel tersebut masih banyak kekurangannya, misalnya passwordnya tetap seperti
"790617", setelah mengeluarkan EXE dan menjalankannya, Anda harus menunggu sampai selesai berjalan lalu menghapusnya, dll. Pembaca dapat memodifikasinya sendiri.