首 页 | 精品电影 | 音乐天堂 | 在线游戏 | Flash MTV | 三湘书屋 | 幽默笑话 | 三湘图库 | 美女写真 | IT知识库 | QQ贴图 | 加入书签

网页制作网络编程图形图象操作系统冲浪宝典软件教学网络安全认证考试通信技术电子商务业内动态书籍教程原码

最近更新 文章分类 多媒体类 精品软件

本站搜索:
您的位置:三湘时空 -> IT知识库 -> 文章分类 -> Delphi -> 项目迭代开发手记--文件分割存储用例的实现过程(3)
项目迭代开发手记--文件分割存储用例的实现过程(3)


文章类别:Delphi 来源: 作者: 发表日期:2006-2-4 字体:[ ]

小游戏 | 在线影院 | 幽默笑话 | 源码下载 | Flash MTV | 音乐试听 | 书屋 | 美女写真

项目迭代开发手记--文件分割存储用例的实现过程(3)
      
上午的迭代2完成后,我们获得了一个有完整压缩流功能的实现代码,这次迭代完成的代码是可用的,我们在迭代2中完成了我们既定的任务。在下午的小组讨论中,我们继续考虑下一阶段的迭代目标,由于没有决定图档文件的格式,我们决定先不考虑图片格式的问题,先实现文件的分割功能。文件的分割主要是考虑当图档文件太大的时,数据库提交性能会变得非常慢,分割的目的就是改进提交的性能。
迭代3:
对向数据库提交的二进制流进行分割压缩;那么从数据库提取的时候要进行解压和拼接操作,以获得原始图档数据。
在分割功能的设计和编码前,我们重新审视了上午的代码——那个压缩类TLoadBinaryDataToDB,发觉该类似乎职责太多,它要负责把文件装载成流,然后才对流进行压缩和解压缩,我们发现UnCompressStream函数有更好的通用性,只要是压缩的流就可以对其进行解压。而压缩功能在这个类里似乎只能对通过文件装载的流进行压缩,如果流是以另一种形式获得的,不是以文件装载的形式,那么我们不知道该如何对该流进行压缩。这里似乎违背了功能单一的职责,类既负责了流的装载,又负责流的压缩;于是我们对该类进行了重构已获得结构更好的的类,以增加类的重用性。
重构后的类只有两个公用的方法 CompressStream 和 UnCompressStream 它们都已流为参数,通过对传入流的处理来实现压缩和解压缩功能。
 
procedure TCompressStream.CompressStream(var stream: TMemoryStream);
var
  iSize: Integer;
  lDestStream: TMemoryStream;
  lCompressionStream: TCompressionStream;
begin
  lDestStream := TMemoryStream.Create;
  lCompressionStream := TCompressionStream.Create(clMax, lDestStream);
  try
    iSize := stream.Size; //获得图像流的原始尺寸
stream.SaveToStream(lCompressionStream); //将原始图像流进行压缩,
// lDestStream中保存着压缩后的图像流
    lCompressionStream.Free;
    stream.Clear;
    stream.WriteBuffer(iSize, SizeOf(iSize)); //写入原始图像的尺寸
    stream.CopyFrom(lDestStream, 0); //写入经过压缩的图像流
  finally
    lDestStream.Free
  end;
end;
 
解压缩函数
procedure TCompressStream.UnCompressStream(var stream: TMemoryStream);
var
  DecompressionStream: TDecompressionStream;
  Buffer: PChar;
  Count: Integer;
begin
  stream.ReadBuffer(Count, SizeOf(Count));
  GetMem(Buffer, Count); //根据图像尺寸大小为将要读入的原始图像流分配内存块
  DecompressionStream := TDecompressionStream.Create(stream);
  try
DecompressionStream.ReadBuffer(Buffer^, Count); //将被压缩的图像流解压缩,
//然后存入 Buffer内存块中
    stream.Clear;
    stream.WriteBuffer(Buffer^, Count); //将原始图像流保存至 stream流中
    stream.Position := 0;
  finally
    FreeMem(Buffer); // 释放内存
  end;
end;
经过重构后,类TCompressStream无疑提高了重用性,同时有更好的结构。除去了把文件装载成流的功能后,TCompressStream职责变得更单一了。它对已任何形式获得得的流都可以进行压缩和解压缩。完成TLoadBinaryDataToDB重构我们开始考虑对流进行分割功能的实现。
在假定一个流被分割成5份,那么拼接时就要有一个顺序我们考虑在数据库增加一个顺序的字段来保存流各个块之间的分割顺序。
字段名
字段类型
字段长度
字段说明
 
FID
Number
 
主键
 
F_NAME
VarChar2
50
文件名称
 
F_SERIAL
Number
 
文件分割顺序号
 
F_BINARY_DATA
Long Row
 
二进制数据
 
同样我们考虑把这个功能封装在一个类里面。我们实现了一个叫TStreamIncise的类,在设计这个类时,我们为了更好的增加对这类要设计成什么样子进行了很好的讨论,首先我们模拟了如何使用该类。
 
  for I := 0 to IncisedCount - 1 do
    begin
      StreamIncise.GetInciseStream(lStream); //获得分割流
      ClientDataSet2.Append;
      ClientDataSet2.FieldByName('F_ID').Value := I; //取序列号
      ClientDataSet2.FieldByName('F_NAME').Value := FFileFullName;
      ClientDataSet2.FieldByName('F_SERIAL').Value := I; // 取每次分割的序列号
      lCompressionStream.CompressStream(lStream);
      (ClientDataSet2.FieldByName('F_BINARY_DATA')
 as TBlobField).LoadFromStream(lStream);
      ClientDataSet2.Post;
end;
我们用代码估计了类的调用方式,通过这样的模拟代码我们获得了以下信息
1)               要获得文件的被分割数,就是说如果使用上面的模拟代码,我们必须先获得流的分割数。
2)               TStreamIncise流在执行前先获得要处理流,同时设定分割块的大小。
 
我们用FInciseSize 来保存分割快的大小值,FStreamSize 保存流的大小值,FRemainSize保存每次分割后的剩余值。FInciseSize 在初始化函数 Create 中初始化。
FInciseSize := 50000; //设置分割的大小
 
LoadFromStream 把原始的流装载过来。
procedure TStreamIncise.LoadFromStream(stream: TMemoryStream);
begin
  FMemoryStream := stream; // 保存一个流的引用
  FStreamSize := stream.Size;
  FRemainSize := FStreamSize;
end;
 
GetIncisedCount 获得装载的原始流要被分割的数量。
function TStreamIncise.GetIncisedCount: Integer;
begin
  Result := FStreamSize div FInciseSize + 1;
end;
SetStreamDefault 用来把获得流设置到初始位置。
procedure TStreamIncise.SetStreamDefault;
begin
  if Assigned(FMemoryStream) then  FMemoryStream.Position :=0;
end;
 
核心的函数是GetInciseStream 通过调用它用户获得分割好后的流。
 
procedure TStreamIncise.GetInciseStream(inciseStream: TMemoryStream);
var
  iMaxError: Integer;
  Count: Integer;
  Buffer: PChar;
begin
  Count := GetBufferCount;
  GetMem(Buffer, Count);
  try
    FMemoryStream.ReadBuffer(Buffer^, Count);
    InciseStream.Clear;
    inciseStream.WriteBuffer(Buffer^, Count);
    InciseStream.Position := 0;
    FRemainSize := FRemainSize - Count;
  finally
    FreeMem(Buffer);
  end;
end;
这里GetBufferCount 每次返回分割块的大小,当剩余的流大小不够5000 时它返回剩下流的长度。
function TStreamIncise.GetBufferCount: Integer;
begin
  Result := FInciseSize;
  if FRemainSize < FInciseSize then
    Result := FRemainSize;
end;
 
最终我们获得了一个可以这样调用的分割类:
procedure TForm1.Button8Click(Sender: TObject);
var
  StreamIncise: TStreamIncise;
  I: Integer;
  lStream: TMemoryStream;
  lCompressionStream: TCompressStream;
begin
  StreamIncise := TStreamIncise.Create;
  lStream := TMemoryStream.Create;
  lCompressionStream := TCompressStream.Create;
  StreamIncise.LoadFromStream(FStream);
  StreamIncise.SetStreamDefault;
  try
    for I := 0 to StreamIncise.IncisedCount - 1 do
    begin
      StreamIncise.GetInciseStream(lStream); //获得分割流
      ClientDataSet2.Append;
      ClientDataSet2.FieldByName('F_ID').Value := I; //取序列号
      ClientDataSet2.FieldByName('F_NAME').Value := FFileFullName;
      ClientDataSet2.FieldByName('F_SERIAL').Value := I; // 取每次分割的序列号
      lCompressionStream.CompressStream(lStream);
      (ClientDataSet2.FieldByName('F_BINARY_DATA')
 as TBlobField).LoadFromStream(lStream);
      ClientDataSet2.Post;
    end;
  finally
    StreamIncise.Free;
    lStream.Free;
    lCompressionStream.Free;
  end;
end;
最后我们增加了InciseSize 属性,让程序员在创建类以后可以自己修改分割块的大小。
通过这样的调用,我们就可以把分割类具体的保存业务的耦合解开,从而增加了分割类下次被重用的可能性。在查阅资料过程中我们也找到一些分割的例子,只是都跟具体的业务耦合得很紧密,要重用该代码除了粘贴复制以外基本上没有他法。

这样当迭代3完成的时候我们实现了对了流的分割压缩,文件分割存储用例到这里获得一个好的解决方案,通过小步的迭代前进我们可以在每一次迭代结束的时候获得可以使用的功能代码,剩下来就使考虑图档文件的格式问题了。其实更主要的通过这次开发我们让新加入的组员获得了一次很好的编程培训,更容易理解要实现一个功能的具体思路和步骤。
上一篇:为什么要选择TCAD来开发矢量应用软件 下一篇:动态建表(示例)
本栏目热门文章
·Delphi工具—反编译Delphi(三) 2006-2-4
·Delphi工具—反编译Delphi(二) 2006-2-4
·Delphi工具——反编译Delphi(一) 2006-2-4
·用FASTREPORT实现WEB应用中自定义报表 2006-2-4
·Delphi中ScriptControl的高级应用(一) 2006-2-4
·利用内存映射文件扩充程序可用的内存 2006-2-4
·QQ聊天记录器演示程序 2006-2-4
·Delphi与DirectShow&amp;DSPack/在 2006-2-4
·UltraEdit也支持Delphi语法高亮 2006-2-4
·DirectShow之接口实战篇(二) 2006-2-4
新近更新文章
·BPCS系统现金流量分析工具开发日志 2006-2-4
·程序间相互通讯问题的解决 2006-2-4
·如何获取本地HTML文件的标题,超级链接 2006-2-4
·建立自己的csdn知识管理库(1) 2006-2-4
·使用Delphi开发多媒体播放音轨问题的FAQ(原创) 2006-2-4
·监视资源管理器的文件变化 2006-2-4
·实现在virtualStringtree中编辑的标准步骤 2006-2-4
·WINDOWS编程技巧之DELPHI篇 2006-2-4
·DELPHI面向对象支持特点--保护级类成员的应用 2006-2-4
·取Run下所有值(原创) 2006-2-4
首 页 | 软件发布 | 广告联系 | 下载帮助 | 意见反馈 | 网站地图
  CopyRight? 2002-2004 WWW.SXSKY.NET? All Rights Reserved
三湘时空 站长QQ:82675303 Email: