我正在做两个函数来加入和分割TFileStream中的文件,代码:
加入
procedure TFormHome.btnJoinClick(Sender: TObject);
var
InStream, OutStream: TFileStream;
OutFileName, InFileName1, InFileName2: string;
begin
OutFileName := 'salida.out';
InFileName1 := 'image.jpg';
InFileName2 := 'test.exe';
OutStream := TFileStream.Create(OutFileName, fmCreate);
try
InStream := TFileStream.Create(InFileName1, fmOpenRead);
ShowMessage(IntToStr(InStream.Size));
try
OutStream.CopyFrom(InStream, InStream.Size);
finally
InStream.Free;
end;
InStream := TFileStream.Create(InFileName2, fmOpenRead);
ShowMessage(IntToStr(InStream.Size));
try
OutStream.CopyFrom(InStream, InStream.Size);
finally
InStream.Free;
end;
finally
OutStream.Free;
end;
end;
鸿沟
procedure TFormHome.btnUnJoinClick(Sender: TObject);
var
Source, Target: TStream;
Buffer: array of Byte;
i: Integer;
SourceName, TargetNames: string;
SizeTargets: Integer;
begin
SourceName := 'salida.out';
TargetNames := 'test.exe';
SizeTargets := 2232832;
Source := TFileStream.Create(SourceName, fmOpenRead);
Target := TFileStream.Create(TargetNames, fmCreate);
try
SetLength(Buffer, SizeTargets);
Source.ReadBuffer(Pointer(Buffer)^, Length(Buffer));
Target.WriteBuffer(Buffer[0], Length(Buffer));
finally
Target.Free;
end;
end;
问题在于,当我分割文件时,可执行文件在我想显示错误时会中断并运行:
Windows can not find the file "route ..." Make sure the name is spelled correctly and try again
或
The version of this file is not compatible with the version of Windows you are running ... (and then talking about 32 or 64 bits)
同时检查第二个函数中可执行文件的大小是否正常。
问题在于,在第二个代码中,所有文件都被破坏了
如何解决这个问题?
答案 0 :(得分:4)
您正在连接多个输入文件,而不在输出中指示一个文件结束而下一个文件开始。您的除法码不知道哪些字节属于JPG,哪些字节属于EXE。
例如,您显示的除法代码是提取JPG字节并将其保存到.exe
文件。当然,.exe
文件无法正常运行。
为了提取EXE,您必须首先提取/跳过JPG,这意味着您必须知道JPG中有多少字节。因此,您需要将输入文件大小存储在连接的输出中,而不仅仅是它们的数据,例如:
procedure TFormHome.btnJoinClick(Sender: TObject);
var
OutStream: TFileStream;
procedure AddFile(const FileName: sstring);
var
InStream: TStream;
Size: Int64;
begin
InStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Size := InStream.Size;
OutStream.WriteBuffer(Size, SizeOf(Size));
OutStream.CopyFrom(InStream, Size);
finally
InStream.Free;
end;
end;
begin
OutStream := TFileStream.Create('salida.out', fmCreate);
try
AddFile('image.jpg');
AddFile('test.exe');
finally
OutStream.Free;
end;
end;
procedure TFormHome.btnUnJoinClick(Sender: TObject);
var
Source: TStream;
procedure SkipFile;
var
Size: Int64;
begin
Source.ReadBuffer(Size, SizeOf(Size));
Source.Seek(Size, soCurrent);
end;
procedure ExtractFile(const FileName: string);
var
Target: TStream;
Size: Int64;
begin
Source.ReadBuffer(Size, SizeOf(Size));
Target := TFileStream.Create(FileName, fmCreate);
try
Target.CopyFrom(Source, Size);
finally
Target.Free;
end;
end;
begin
Source := TFileStream.Create('salida.out', fmOpenRead or fmShareDenyWrite);
try
SkipFile;
ExtractFile('test.exe');
finally
Source.Free;
end;
end;
我建议您考虑存储文件名:
procedure TFormHome.btnJoinClick(Sender: TObject);
var
OutStream: TFileStream;
procedure AddFile(const FileName: string);
var
InStream: TStream;
Name: UTF8String;
Len: Integer;
FileSize, TotalSize: Int64;
begin
InStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Name := UTF8String(ExtractFileName(FileName));
Len := Length(Name);
FileSize := InStream.Size;
TotalSize := SizeOf(Len) + Len + SizeOf(FileSize) + FileSize;
OutStream.WriteBuffer(TotalSize, SizeOf(TotalSize));
OutStream.WriteBuffer(Len, SizeOf(Len));
OutStream.WriteBuffer(PAnsiChar(Name)^, Len);
OutStream.WriteBuffer(FileSize, SizeOf(FileSize));
OutStream.CopyFrom(InStream, FileSize);
finally
InStream.Free;
end;
end;
begin
OutStream := TFileStream.Create('salida.out', fmCreate);
try
AddFile('image.jpg');
AddFile('test.exe');
finally
OutStream.Free;
end;
end;
procedure TFormHome.btnUnJoinClick(Sender: TObject);
var
Source: TStream;
procedure SkipFile;
var
TotalSize: Int64;
begin
Source.ReadBuffer(TotalSize, SizeOf(TotalSize));
Source.Seek(TotalSize, soCurrent);
end;
procedure ExtractFile;
var
Target: TStream;
TotalSize, FileSize: Int64;
Name: UTF8String;
Len: Integer;
Pos: Int64;
begin
Source.ReadBuffer(TotalSize, SizeOf(TotalSize));
Pos := Source.Position;
Source.ReadBuffer(Len, SizeOf(Len));
SetLength(Name, Len);
Source.ReadBuffer(PAnsiChar(Name)^, Len);
Source.ReadBuffer(FileSize, SizeOf(FileSize));
Target := TFileStream.Create(String(Name), fmCreate);
try
Target.CopyFrom(Source, FileSize);
finally
Target.Free;
end;
if (Source.Position - Pos) <> TotalSize then
raise Exception.Create('Extract failed. Bad position');
end;
begin
Source := TFileStream.Create('salida.out', fmOpenRead or fmShareDenyWrite);
try
SkipFile;
ExtractFile;
finally
Source.Free;
end;
end;