首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将文件拆分为TFileStream

将文件拆分为TFileStream
EN

Stack Overflow用户
提问于 2016-09-22 01:45:53
回答 1查看 944关注 0票数 2

我正在执行两个函数来连接和分割TFileStream中的文件,代码如下:

加入

代码语言:javascript
复制
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;

除法

代码语言:javascript
复制
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;

问题是,当我划分文件时,当我想显示如下错误时,可执行文件中断并运行:

代码语言:javascript
复制
  Windows can not find the file "route ..." Make sure the name is spelled correctly and try again

代码语言:javascript
复制
  The version of this file is not compatible with the version of Windows you are running ... (and then talking about 32 or 64 bits)

另外,检查第二个函数中可执行文件的大小是否正确。

问题是,在第二个代码中,所有的文件都被破坏了

我该如何解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-22 03:28:23

您正在将多个输入文件联接在一起,而没有在输出中指明一个文件的结束位置和下一个文件的开始位置。divide代码不知道哪些字节属于JPG,哪些字节属于EXE。

例如,您所显示的divide代码提取JPG字节并将它们保存到.exe文件中。所以.exe文件当然不会正确运行。

为了提取EXE,您必须首先提取/跳过JPG,这意味着您必须知道JPG中有多少字节。因此,您需要将输入文件大小存储在连接的输出中,而不仅仅是它们的数据,例如:

代码语言:javascript
复制
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;

我建议您也考虑存储文件名:

代码语言:javascript
复制
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;
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39623278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档