用TDeCompressionStream解压缩报错out of memory,求解。。

fky1989 2013-07-30 10:25:23
procedure TForm1.btn2Click(Sender: TObject);
var
ds: TDecompressionStream;
dm, sm: TMemoryStream;
num: Int64;
begin
sm := TMemoryStream.Create;
sm.LoadFromFile('f:\c.zipx');
sm.Read(num, SizeOf(num));

// num读出来后是4977709564142869112
// 文件大小有117M

dm := TMemoryStream.Create;
dm.SetSize(num); //运行到这里 out of memory 报错。不支持这么大的文件的原因么??

pb1.Max := Integer(num div 1024);

ds := TDecompressionStream.Create(sm);
ds.OnProgress := dsProcess;

ds.Read(dm.Memory^, num);
dm.SaveToFile('f:\d.exe');

dm.Free;
sm.Free;
ds.Free;
end;
...全文
227 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamduo 2013-08-09
  • 打赏
  • 举报
回复
仔细检查每一步的 Stream 对象的 Position,是不是没有赋值 0. 还有,我那段代码能用吗? 如果能用,你比对一下。
iamduo 2013-07-30
  • 打赏
  • 举报
回复
LoadFromFile 之后能确定 Position 等于 0 吗? 你这个 num 是不是也太大了点吧?不像是 117M 的样子。
fky1989 2013-07-30
  • 打赏
  • 举报
回复
很是奇怪。为什么我压缩后的*.zip打开后里面是空的
iamduo 2013-07-30
  • 打赏
  • 举报
回复
我不是很肯定以下代码是否可用。 不过,lz 可以借鉴一下。

{-------------------------------------------------------------------------------
 单元名: uDuoZlib.pas
 功能  : 简单压缩 -- Zlib
 作者  : Duo
 日期  :2010-04-28 22:04:09
 说明  :压缩解压 流,文件
         字符串压缩使用类方法,如果字符串过短,还是不要压缩的好。反而变大。
-------------------------------------------------------------------------------}
unit uDuo.Zlib;

interface

uses SysUtils,Classes,ZLib,Forms;

type
  TZlibOnProgressEvent = procedure (AFileSize,AFilePos:Int64) of object;

  TZlib=class
  private
    FFilePos: Int64;
    FFileSize: Int64;
    FOnProgress: TZlibOnProgressEvent;
    procedure CsProgress(Sender:TObject); // 压缩
    procedure DsProgress(Sender:TObject); // 解压
  public
    procedure CompressionStream(ASourceStream,ATargetStream:TStream);
    procedure DecompressionStream(ASourceStream,ATargetStream:TStream);
    procedure CompressionFile(const ASourceFile,ATargetFile:TFileName);
    procedure DecompressionFile(const ASourceFile,ATargetFile:TFileName);

    // 直接使用的函数,没有进度条
    class function CompressionString(const ASource:string):String;
    class function DecompressionString(const ASource:String):String;

    property FileSize:Int64 read FFileSize;
    property FilePos:Int64 read FFilePos;
    property OnProgress:TZlibOnProgressEvent read FOnProgress write FOnProgress;
  end;

implementation

{ TZlib }

procedure TZlib.CompressionFile(const ASourceFile, ATargetFile: TFileName);
var
  fs,ms:TMemoryStream;
begin
  fs := TMemoryStream.Create;
  ms := TMemoryStream.Create;
  try
    fs.LoadFromFile(ASourceFile);
    CompressionStream(fs,ms);
    ms.SaveToFile(ATargetFile);
  finally
    ms.Free;
    fs.Free;
  end;
end;

procedure TZlib.CompressionStream(ASourceStream,ATargetStream:TStream);
var
  cs:TCompressionStream;
begin
  FFileSize := ASourceStream.Size;
  if FFileSize > 0 then
  begin
    cs := TCompressionStream.Create(clMax,ATargetStream);
    try
      cs.OnProgress := CsProgress;
//      ASourceStream.Position := 0; // no use ???
      cs.CopyFrom(ASourceStream,0);
    finally
      cs.Free;
    end;
  end;
end;

class function TZlib.CompressionString(const ASource: string): String;
var
  buffer: Pointer;
  size: Integer;
begin
  CompressBuf(PChar(ASource),Length(ASource),buffer,size);
  SetLength(Result,size);
  Move(buffer^,Pointer(Result)^,size);
  FreeMem(buffer);
end;

procedure TZlib.CsProgress(Sender: TObject);
begin
  FFilePos := TCompressionStream(Sender).Position;
  if Assigned(FOnProgress) then
    FOnProgress(FFileSize,FFilePos);
  Application.ProcessMessages;
end;

procedure TZlib.DecompressionFile(const ASourceFile,
  ATargetFile: TFileName);
var
  fs,ms:TMemoryStream;
begin
  fs := TMemoryStream.Create;
  ms := TMemoryStream.Create;
  try
    fs.LoadFromFile(ASourceFile);
    DecompressionStream(fs,ms);
    ms.SaveToFile(ATargetFile);
  finally
    ms.Free;
    fs.Free;
  end;
end;

procedure TZlib.DecompressionStream(ASourceStream,ATargetStream:TStream);
var
  ds:TDecompressionStream;
begin
  FFileSize := ASourceStream.Size;
  if FFileSize > 0 then
  begin
    ASourceStream.Position := 0;
    ds := TDecompressionStream.Create(ASourceStream);
    try
      ds.OnProgress := DsProgress;
      FFileSize := ATargetStream.CopyFrom(ds,FFileSize);
      ATargetStream.Size := FFileSize;
    finally
      ds.Free;
    end;
  end;
end;

class function TZlib.DecompressionString(const ASource: String): String;
var
  buffer: Pointer;
  size: Integer;
begin
  DecompressBuf(PChar(ASource),Length(ASource),0,buffer,size);
  SetLength(Result,size);
  Move(buffer^,Pointer(Result)^,size);
  FreeMem(buffer);
end;

procedure TZlib.DsProgress(Sender: TObject);
begin
  FFilePos := TDecompressionStream(Sender).Position;
  if Assigned(FOnProgress) then
    FOnProgress(FFileSize,FFilePos);
  Application.ProcessMessages;
end;

end.

fky1989 2013-07-30
  • 打赏
  • 举报
回复
引用 1 楼 iamduo 的回复:
LoadFromFile 之后能确定 Position 等于 0 吗? 你这个 num 是不是也太大了点吧?不像是 117M 的样子。
我换用delphi帮助里的方法。。解压矢耦还是报错郁闷啊,data error。 我压缩一个文件后,这个*.zip打开是空的。这个压缩方法是把文件直接压缩,还是添加到压缩文件里啊? 还是我写错了??但全是按照帮助的example写的啊
procedure TForm1.btn1Click(Sender: TObject);
var
  LZip: TCompressionStream;
  LInput, LOutput: TFileStream;
  Num: Int64;
begin
  if not dlgSave1.Execute then
    Exit;
  LInput := TFileStream.Create(lst1.Items[lst1.ItemIndex], fmOpenRead);
  try
    Num := LInput.Size;

    LOutput := TFileStream.Create(dlgSave1.FileName, fmCreate);
    try
      LOutput.Write(Num, SizeOf(Num));

      LZip := TCompressionStream.Create(clMax, LOutput);
      try
        pb1.Max := Integer(Num div 1024);
        LZip.OnProgress := csProcess;
        LZip.CopyFrom(LInput, LInput.Size);
      finally
        LZip.Free;
      end;

    finally
      LOutput.Free;
    end;
  finally
    LInput.Free;
  end;
end;

procedure TForm1.btn2Click(Sender: TObject);
var
  LUnZip: TDecompressionStream;
  LInput, LOutput: TFileStream;
  Num: Int64;
begin
  if not dlgSave1.Execute then
    Exit;
  LInput := TFileStream.Create(lst1.Items[lst1.ItemIndex], fmOpenRead);
  try
    Num := LInput.Size;

    LOutput := TFileStream.Create(dlgSave1.FileName, fmCreate);
    try
      LUnZip := TDecompressionStream.Create(LInput);
      try
//        pb1.Max := Integer(LInput.Size);
//        LUnZip.OnProgress := dsProcess;
        LOutput.CopyFrom(LUnZip, 0);
      finally
        LUnZip.Free;
      end;
    finally
      LOutput.Free;
    end;
  finally
    LInput.Free;
  end;
end;

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧