如何将Tstream合并和读取(100分)

  • 主题发起人 主题发起人 sweidong
  • 开始时间 开始时间
S

sweidong

Unregistered / Unconfirmed
GUEST, unregistred user!
如何将Tstream1,Tstream2…Tstream n个,合并成一个Tstream,
而后还能从合并后的Tstream中读取其中的任意一个Tstream。最好给出代码!谢谢!
 
var n:integer;
oldstream1,oldstream2:Tmemorystrem
newstream:Tmemorystream;
begin
newstream:=Tmemorystream.create
try
with newstream do
begin
n:=oldstream.size
//第一个stream的大小
write(n,size(n))
//先写大小
copyfrom(oldstream1,0)
//合并oldstream1
n:=oldstream2.size
//第二个stream的大小
write(n,sizeof(n))
//合并oldstream2
copyfrom(oldstream2.0)
........
end;

with oldstream1 do //分解oldstream1
begin
seek(0,sofrombeginning)
//移到开始
newstream.read(n,sizeof(n)
//长度
copyfrom(newstream,n)

end;
with oldstream2 do //分解oldstream2
begin
seek(0,sofrombeginning)
//移到开始
newstream.read(n,sizeof(n)
//长度
copyfrom(newstream,n)

end;

finally
newstream.free;
end;
end;

 
你的方法不能做到读取任意Tstream!
 
你自己要建立一个各个stream在合并后stream中的对应表,然后按照上述实现方法就可以
读取任意的STream
 
为什么不能,这只是示例,什么filestream,stringstream等都由stream派生的。
你想读什么就读什么
 
to bianlx:如何建对应表,可否教我!
to myname:你怎么知道那个stream在什么位置,如果按顺序还好,可是我要任意!
而且我是先写入文件,然后再从文件中读。
 
这还不简单吗:
在最前面写一个文件头,比如每个stream占用512Byte,记录该stream名称、长度、起如位置、
结束位置等。读的时候随便读那一个都没问题
 
我搞过文件合并和分割!你看看我的软件:http://smhp.myetang.com/
 
http://smhp.myetang.com/ebook.zip
 
to sima:
不错,可是没有源码,我学不到。你能否提供合并文件,读取文件这一段源码。谢谢!
 
我的每个stream大小都不一样,你可否教我如何写这个文件头,又该如何读!谢谢!
意思也就像excell工作簿的保存和每个sheet的读写!
 
http://ailine_xinghe.home.chinaren.com 上我的作品里面有一个捆绑机的源代码,
还没作完,我不想作了,可以完全解决你的问题,是用了一个很笨蛋的方法,就是在最后
捆绑了一个txt 记录各个文件的文件名,大小,等等具体情况,本来打算写一篇关于这个
问题的文章的,毕业中,很忙,去了一家软件公司,学习中,很忙,
很累!
 
三行搞定,肯定对任意 Stream 均适用:
procedure CombStream(aStream, bStream, ResStream: TStream);
begin
ResStream.CopyFrom(aStream, 0);
ResStream.CopyFrom(bStream, 0);
ResStream.Position := 0;
end;

测试通过:
procedure TForm1.Button1Click(Sender: TObject);
var
a, b, c: TMemoryStream;
begin
a := TMemoryStream.Create;
b := TMemoryStream.Create;
c := TMemoryStream.Create;
a.LoadFromFile('c:/17#.txt');
b.LoadFromFile('c:/18#.txt');
CombStream(a, b, c);
c.SaveToFile('c:/1718#.txt');
a.Free;
b.Free;
c.Free;
end;
 
to beta:
对合并好的c,我只想读取b的内容该如何办?这是我问的关键!
 
我们先写一个添加函数,该函数的功能是把一个文件当作一个流添加到另外一个文件的尾部。函数如下:

Function Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
var
Target,Source:TFileStream;
MyFileSize:integer;
begin
try
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareExclusive);
Target:=TFileStream.Create(TargetFile,fmOpenWrite or fmShareExclusive);
try
Target.Seek(0,soFromEnd);//往尾部添加资源
Target.CopyFrom(Source,0);
MyFileSize:=Source.Size+Sizeof(MyFileSize);//计算资源大小,并写入辅程尾部
Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));
finally
Target.Free;
Source.Free;
end;
except
Result:=False;
Exit;
end;
Result:=True;
end;
有了上面的基础,我们应该很容易看得懂这个函数。其中参数SourceFile是要添加的文
件,参数TargetFile是被添加到的目标文件。比如说把a.exe添加到b.exe里面可以:
Cjt_AddtoFile('a.exe',b.exe');如果添加成功就返回True否则返回假。
根据上面的函数我们可以写出相反的读出函数:
Function Cjt_LoadFromFile(SourceFile,TargetFile :string):Boolean;
var
Source:TFileStream;
Target:TMemoryStream;
MyFileSize:integer;
begin
try
Target:=TMemoryStream.Create;
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone);
try
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//读出资源大小
Source.Seek(-MyFileSize,soFromEnd);//定位到资源位置
Target.CopyFrom(Source,MyFileSize-sizeof(MyFileSize));//取出资源
Target.SaveToFile(TargetFile);//存放到文件
finally
Target.Free;
Source.Free;
end;
except
Result:=false;
Exit;
end;
Result:=true;
end;
其中参数SourceFile是已经添加了文件的文件名称,参数TargetFile是取
出文件后保存的目标文件名。比如说Cjt_LoadFromFile('b.exe','a.txt');

这两个函数,一个加入,一个读取,你看看有没有用
 
合并:
procedure CombineStream(SrcName: string
Src, Dst: TStream);
var
l: Integer;
begin
l := length(srcname);
with dst do
begin
writebuffer(l, sizeof(integer));
writebuffer(srcname[1], l);
l := src.size;
writebuffer(l, sizeof(integer));
copyfrom(src);
end;
end;

读取:
procedure ReadAnyStream(Dst, Src: TStream
Name: string);
var
l: Integer;
buffer: string;
begin
with src do
begin
seek(0,0);
repeat
readbuffer(l, sizeof(integer));
setlength(buffer, l);
readbuffer(buffer[1], l);
readbuffer(l, sizeof(integer));
if buffer=name then
begin
dst.copyfrom(src, l);
break;
end
else seek(1, l);
until position >= size;
end;
end;
 
//对合并好的c,我只想读取b的内容该如何办?
你把两个面团揉在一起过后还能分成原来的样子吗?
除非自己加标记了,不过那就麻烦了:(
 
有例子,收信!
 
Pearl 的方法是可行的,当然,如果用整型数值代替 string 作为标记则更快一点:)
 
后退
顶部