在内存中解压,好像要建立自己的文件系统,如何实现?(300分)

  • 主题发起人 主题发起人 魏启明
  • 开始时间 开始时间

魏启明

Unregistered / Unconfirmed
GUEST, unregistred user!
[red]其实我主要的目的是打包和加密,压缩倒不是重要的,就是使用包内文件时,不需要搞到临时文件里面,包内要有文件目录体系等,直接以文件方式访问[/red]

Office2007的文件格式 或 很多软件的皮肤文件,是用Zip格式压缩的,他们在使用的时候,并没有解压到临时文件夹中,请问是如何实现的?
还有很多的游戏,都对自身的资源进行了打包;VSS的库文件分散在多个文件中,通过自己的软件则可实现文件的树结构。

我找了很多资料,不过基本是语焉不详,有两篇提到要建立文件系统,搞不懂啊?

哪位大拿能提供一下资料,组件之类的技术,能解释清楚的最好了。

只要能实现Zip或其他可控制的压缩格式的内存解压读取就可以了,用Delphi中压缩
Zip的也可以


我出了300分,不过没有好答案我是不会放分的,顶也是顶不到分的。
 
LZ看下对你是否有帮助
procedure TForm1.Button5Click(Sender: TObject);
var
ms,mt:TMemoryStream;
fn:string;
SourceStream:TCompressionStream;
Count:Integer;
begin
if opendialog2.Execute and FileExists(opendialog2.FileName) then
begin
fn:=opendialog2.FileName;
ms:=TMemoryStream.Create;
ms.LoadFromFile(fn);
{ Count:=ms.Size;
mt:=TMemoryStream.Create;
//构建压缩流
SourceStream:=TCompressionStream.Create(clMax,mt);
try
ms.SaveToStream(SourceStream);
SourceStream.Free;
ms.Clear;
ms.CopyFrom(mt,0);
Count:=ms.Size; }
with adq1 do
begin
adq1.Insert;
// (FieldByName('avi') as TBlobField).LoadFromStream(ms);
(FieldByName('avi') as TBlobField).LoadFromStream(zstream(ms));
post;
end;
{ finally
ms.Free;
mt.Free;
end; }
end;
end;

procedure TForm1.Button6Click(Sender: TObject);
var
ms:TMemoryStream;
// SourceStream:TDecompressionStream;
Count:Integer;
path:string;
Buffer:pointer;
begin
path:=ExtractFilePath(Application.ExeName);
ms:=TMemoryStream.Create;
try
with adq1 do
begin
adq1.Edit;
(FieldByName('avi') as TBlobField).SaveToStream(ms);
adq1.Cancel;
{// ms.Position := 0;
ms.ReadBuffer(Count, Sizeof(Count));
GetMem(Buffer,Count);
SourceStream := TDecompressionStream.Create(ms);
try
SourceStream.readBuffer(Buffer^,Count);
//将数据流保存至ms流中
ms.Clear;
ms.writeBuffer(Buffer^,Count);
ms.Position := 0;//复位流指针
Count:=ms.Size;
}
ms:=UnZStream(ms);
ms.SaveToFile(path+'456.avi');
// SourceStream.Free;
// except

// end;
end;
finally
ms.Free;
end;
end;



function ZStream(var CompressedStream:TMemoryStream):TMemoryStream;
var
SourceStream:TCompressionStream;
DestStream:TMemoryStream;
Count:Integer;
Begin
//获得数据流的原始尺寸
Count:=CompressedStream.Size;
DestStream:=TMemoryStream.Create;
SourceStream:=TCompressionStream.Create(clMax,DestStream);
Try
//SourceStream中保存着原始的数据流
CompressedStream.SaveToStream(SourceStream);
//将原始数据流进行压缩,DestStream中保存着压缩后的数据流
SourceStream.Free;
with CompressedStream do begin
Clear;
//写入原始数据流尺寸
WriteBuffer(Count,SizeOf(Count));
//写入经过压缩的数据流
CopyFrom(DestStream,0);
//恢复流指针
Position:=0;
end;
finally
DestStream.Free;
end;
Result:=CompressedStream;
end;

function UnZStream(var res:TMemoryStream):TMemoryStream;
//解压缩文件数据流
var
SourceStream:TDecompressionStream;
Buffer:PChar;
Count:Integer;
src:TMemoryStream;
Begin
res.Position:=0;
//从被压缩的数据流中读出原始数据流尺寸
res.ReadBuffer(Count,SizeOf(Count));
//根据数据流尺寸大小为将要读入的原始数据流分配内存块
GetMem(Buffer,Count);
SourceStream := TDecompressionStream.Create(res);
Try
//将被压缩的数据流解压缩,然后存入Buffer内存块中
SourceStream.readBuffer(Buffer^,Count);
//将数据流保存至res流中
res.Clear;
res.writeBuffer(Buffer^,Count);
res.Position:=0;//复位流指针
finally
FreeMem(Buffer);
end;
Result:=res;
end;
 
只要对Zip格式了解,写出在内存中压缩和解压并不困难,目前有很多控件了,看一下它们的实现,并改进一下应该不难
 
呵呵,都没有看明白啊,看明白再回复吧。建议多想想,

重申,不是解压的问题,是直接读包内文件的问题

http://www.cppblog.com/mybios/archive/2006/11/19/15414.html
这篇文章讲的有点意思,但是,它只能读不能写,并且下载不到。
 
啧啧, LZ, 如果只是直接读写ZIP里面的文件, 有何难哉. 直接从轮子做起, 我肯定不能, 不过借助目前已经有的代码和控件, 实现你的要求很容易, 至少可以让你使用TStream类来直接访问包内文件. 看来你也没看清我的回复.

退一步说, 就算不想使用已有的代码, 而设计一个类似ZIP格式的包, 也是不难的.
 
简单点的,用vclzip控件提供的解压到流和从流中压缩
就是读取一个文件包,然后抽取需要的数据到内存,不难的。

不过,如果你是要读取资源包,然后向其他程序提供文件,那就要麻烦多了。首先看看对方支持什么接口,然后再决定如何做了
 
hookapi
打开文件
关闭文件
seek
read
write

重定向到内存
 
后退
顶部