hxFileRes.pas
上传用户:youjie821
上传日期:2013-01-27
资源大小:459k
文件大小:12k
源码类别:

PlugIns编程

开发平台:

Delphi

  1. unit hxFileRes;
  2. interface
  3. uses
  4.   Windows, Classes, SysUtils, ComCtrls, ComStrs, hxClasses;
  5. const
  6.   { 定义消息 }
  7.   FILE_LIST     = $00000001;
  8.   FILE_INFO     = $00000002;
  9.   FILE_DOWNLOAD = $00000003;
  10.   { 网络超时 }
  11.   G_TIMEOUT     = 10000;
  12. type
  13.   { 资源文件类型 }
  14.   TResType = (rtFile, rtDirectory, rtExecute);
  15.   { 版本类型 }
  16.   TVersion = string;
  17.   { 资源文件信息 }
  18.   PResInfo = ^TResInfo;
  19.   TResInfo = packed record
  20.     FileName: string;   // 文件名(不包括路径)
  21.     Description: string;// 文件描述
  22.     FileSize: Integer;  // 文件大小 
  23.     FileAttr: Integer;  // 文件属性
  24.     ModifyTime: TDateTime;// 修改时间
  25.     Version: TVersion;    // 版本号(IP地址格式)
  26.     ResType: TResType;  // 资源类型
  27.     DownloadURL: string;// 下载文件的相对路径
  28.   end;
  29.   TErrorObject = class(Exception);
  30.   TResTree = class;
  31.   { 文件结点 }
  32.   TResNode = class(TNode)
  33.   protected
  34.     procedure SaveMe(Stream: TStream); override;
  35.     procedure LoadMe(Stream: TStream); override;
  36.   end;
  37.   { 文件树 }
  38.   TResTree = class(TTree)
  39.   private
  40.     FRootDir: string; // 根目录的实际路径
  41.     procedure SearchFiles(APath: string; Mask: string; var Node: TNode);
  42.     function ExtractRelativePath(FileName: string): string;
  43.   protected
  44.     function CreateNode: TNode; override;
  45.   public
  46.     procedure Clear; override;
  47.     procedure LoadFiles(Directory: string);
  48.     function AddDirectory(ParentNode: TResNode; Directory: string): TResNode;
  49.     function AddFile(ParentNode: TResNode; AFileName: string): TResNode;
  50.     procedure LoadFromFile(FileName: string);
  51.     procedure SaveToFile(FileName: string);
  52.   end;
  53.   { 客户端保存的版本信息 }
  54.   PVersionInfo = ^TVersionInfo;
  55.   TVersionInfo = record
  56.     FileName: string; // 文件名(包括相对路径)
  57.     Version: TVersion;  // 版本号
  58.   end;
  59.   PVerInfo = ^TVerInfo;
  60.   TVerInfo = record
  61.     FileName: PChar;
  62.     Version: PChar;
  63.   end;
  64.   { 历史版本列表 }
  65.   TVersionList = class(TObject)
  66.   private
  67.     FVersions: TList;
  68.     FFileName: string;
  69.     function GetCount: Integer;
  70.     function GetItems(Index: Integer): PVersionInfo;
  71.     procedure Add(AFileName: string; AVersion: string);
  72.     function GetVersions(FileName: string): TVersion;
  73.     procedure SetVersions(FileName: string; const Value: TVersion);
  74.   public
  75.     constructor Create(FileName: string);
  76.     destructor Destroy; override;
  77.     procedure Clear;
  78.     function IndexOf(FileName: string): Integer;
  79.     procedure Update(FileName: string; Version: TVersion);
  80.     procedure SaveToFile;
  81.     procedure LoadFromFile;
  82.     property Items[Index: Integer]: PVersionInfo read GetItems; default;
  83.     property Versions[FileName: string]: TVersion read GetVersions write SetVersions;
  84.     property Count: Integer read GetCount;
  85.   end;
  86.   // 版本比较函数
  87.   function SameVersion(V1, V2: TVersion): Boolean;
  88. implementation
  89. uses
  90.   hxSysUtils, hxVersion;
  91. function SameVersion(V1, V2: TVersion): Boolean;
  92. begin
  93.   Result:= SameText(V1, V2);
  94. end;
  95. procedure StreamWriteResInfo(Stream: TStream; ResInfo: TResInfo);
  96. begin
  97.   with ResInfo do
  98.   begin
  99.     StreamWriteString(Stream, FileName);   // 包括相对路径(如MyDirMyfile.exe)
  100.     StreamWriteString(Stream, Description);// 描述信息
  101.     StreamWriteInteger(Stream, FileSize);  // 文件大小 
  102.     StreamWriteInteger(Stream, FileAttr);  // 文件属性
  103.     StreamWriteString(Stream, Version);    // 版本号(IP地址格式)
  104.     StreamWriteByte(Stream, Byte(ResType));// 资源文件类型
  105.     StreamWriteString(Stream, DownloadURL);// 资源的相对下载路径
  106.   end;
  107. end;
  108. function StreamReadResInfo(Stream: TStream): TResInfo;
  109. begin
  110.   with Result do
  111.   begin
  112.     FileName:= StreamReadString(Stream);   // 包括相对路径(如MyDirMyfile.exe)
  113.     Description:= StreamReadString(Stream);// 描述信息
  114.     FileSize:=  StreamReadInteger(Stream); // 文件大小 
  115.     FileAttr:= StreamReadInteger(Stream);  // 文件属性
  116.     Version:= StreamReadString(Stream);    // 版本号(IP地址格式)
  117.     ResType:= TResType(StreamReadByte(Stream)); // 资源文件类型
  118.     DownloadURL:= StreamReadString(Stream); // 资源的相对下载路径
  119.   end;
  120. end;
  121. { TResNode }
  122. procedure TResNode.LoadMe(Stream: TStream);
  123. var
  124.   pInfo: PResInfo;
  125. begin
  126.   inherited;
  127.   Text:= StreamReadString(Stream);
  128.   New(pInfo);
  129.   pInfo^:= StreamReadResInfo(Stream);
  130.   Data:= pInfo;
  131. end;
  132. procedure TResNode.SaveMe(Stream: TStream);
  133. begin
  134.   inherited;
  135.   StreamWriteString(Stream, Text);
  136.   StreamWriteResInfo(Stream, PResInfo(Data)^);
  137. end;
  138. { ThxResTree }
  139. function TResTree.ExtractRelativePath(FileName: string): string;
  140. begin
  141.   if Pos(FRootDir, FileName) = 1 then
  142.     Result:= copy(FileName, Length(FRootDir) + 1, Length(FileName) - Length(FRootDir))
  143.   else
  144.     raise Exception.Create('文件名错误,无法找到相对路径!');
  145. end;
  146. function TResTree.CreateNode: TNode;
  147. begin
  148.   Result:= TResNode.Create(Self);
  149. end;
  150. procedure TResTree.LoadFiles(Directory: string);
  151. var
  152.   ResNode: TNode;
  153. begin
  154.   FRootDir:= FormatDirectoryName(Directory);
  155.   Clear;    // 删除所有结点,并且释放结点数据
  156.   ResNode:= RootNode;
  157.   ResNode.Text:= FRootDir;
  158.   SearchFiles(Directory, '*.*', ResNode);
  159. end;
  160. function TResTree.AddDirectory(ParentNode: TResNode; Directory: string): TResNode;
  161.   function GetDirectoryName: string;
  162.   begin
  163.     Result:= FormatDirectoryName(Directory);
  164.     delete(Result, Length(Result), 1);
  165.     Result:= ExtractFileName(Directory);
  166.   end;
  167. var
  168.   Node: TNode;
  169.   pInfo: PResInfo;
  170. begin
  171.   FRootDir:= ParentNode.Tree.RootNode.Text;
  172.   // 添加目录
  173.   New(pInfo);
  174.   with pInfo^ do
  175.   begin
  176.     FileName:= GetDirectoryName;
  177.     Description:= GetFileDescription(Directory);
  178.     FileSize:= 0;
  179.     FileAttr:= 16;
  180.     Version:= GetFileVersion(Directory);
  181.     ResType:= rtDirectory;
  182.     DownloadURL:= ExtractRelativePath(Directory);
  183.   end;
  184.   Node:= AddNode(ParentNode, pInfo^.FileName);
  185.   Node.Data:= pInfo;
  186.   Result:= TResNode(Node);
  187.   SearchFiles(Directory, '*.*', Node);
  188. end;
  189. procedure TResTree.SearchFiles(APath, Mask: string; var Node: TNode);
  190.   function IsDirNotation(ADirName: string): Boolean;
  191.   begin
  192.     Result:= (ADirName = '.') or (ADirName = '..');
  193.   end;
  194. var
  195.   srFile, srDir: TSearchRec;
  196.   FindResult: Integer;
  197.   pInfo: PResInfo;
  198. begin
  199.   APath:= FormatDirectoryName(APath);
  200.   FindResult:= FindFirst(APath + Mask, faAnyFile + faHidden + faSysFile + faReadOnly, srFile);
  201.   try
  202.     // 先找文件
  203.     while FindResult = 0 do
  204.     begin
  205.       New(pInfo);
  206.       with pInfo^ do
  207.       begin
  208.         FileName:= srFile.Name;
  209.         Description:= GetFileDescription(srFile.Name);
  210.         FileSize:= srFile.Size;
  211.         FileAttr:= srFile.Attr;
  212.         ModifyTime:= FileDateToDateTime(FileAge(APath + srFile.Name));
  213.         Version:= GetFileVersion(APath + srFile.Name);
  214.         ResType:= rtFile;
  215.         DownloadURL:= ExtractRelativePath(APath + srFile.Name);
  216.       end;
  217.       AddNode(Node, pInfo^.FileName).Data:= pInfo;
  218.       FindResult:= FindNext(srFile);
  219.     end;
  220.     // 再找目录
  221.     FindResult:= FindFirst(APath + Mask, faDirectory, srDir);
  222.     while FindResult = 0 do
  223.     begin
  224.       if ((srDir.Attr and faDirectory) = faDirectory) and not IsDirNotation(srDir.Name) then
  225.       begin
  226.         New(pInfo);
  227.         with pInfo^ do
  228.         begin
  229.           FileName:= srDir.Name;
  230.           Description:= GetFileDescription(srDir.Name);
  231.           FileSize:= srDir.Size;
  232.           FileAttr:= srDir.Attr;
  233.           Version:= GetFileVersion(srDir.Name);
  234.           ResType:= rtDirectory;
  235.           DownloadURL:= ExtractRelativePath(APath + srDir.Name);
  236.         end;
  237.         Node:= AddNode(Node, pInfo^.FileName);
  238.         Node.Data:= pInfo;
  239.         SearchFiles(APath + srDir.Name, Mask, Node); // Recursion here
  240.         Node:= Node.Parent;
  241.       end;
  242.       FindResult:= FindNext(srDir);
  243.     end;
  244.   finally
  245.     FindClose(srFile);
  246.   end;
  247. end;
  248. procedure TResTree.Clear;
  249. var
  250.   I: Integer;
  251. begin
  252.   // 删除数据(注意:根结点没有数据,不能释放!)
  253.   for I:= 1 to Count - 1 do
  254.     Dispose(PResInfo(Items[I].Data));
  255.   // 删除结点
  256.   inherited Clear;;
  257. end;
  258. procedure TResTree.LoadFromFile(FileName: string);
  259. var
  260.   Stream: TStream;
  261. begin
  262.   Clear;
  263.   if not FileExists(FileName) then Exit;
  264.   Stream:= TFileStream.Create(FileName, fmOpenRead);
  265.   try
  266.     LoadFromStream(Stream);
  267.   finally
  268.     Stream.Free;
  269.   end;
  270. end;
  271. procedure TResTree.SaveToFile(FileName: string);
  272. var
  273.   Stream: TStream;
  274. begin
  275.   if FileExists(FileName) then DeleteFile(FileName);
  276.   Stream:= TFileStream.Create(FileName, fmCreate);
  277.   try
  278.     SaveToStream(Stream);
  279.   finally
  280.     Stream.Free;
  281.   end;
  282. end;
  283. { TVersionList }
  284. procedure TVersionList.Add(AFileName, AVersion: string);
  285. var
  286.   pInfo: PVersionInfo;
  287. begin
  288.   New(pInfo);
  289.   with pInfo^ do
  290.   begin
  291.     FileName:= AFileName;
  292.     Version:= AVersion;
  293.   end;
  294.   FVersions.Add(pInfo);
  295. end;
  296. procedure TVersionList.Clear;
  297. var
  298.   I: Integer;
  299. begin
  300.   for I:= FVersions.Count - 1 downto 0 do
  301.     Dispose(PVersionInfo(FVersions[I]));
  302.   FVersions.Clear;
  303. end;
  304. constructor TVersionList.Create(FileName: string);
  305. begin
  306.   FFileName:= FileName;
  307.   FVersions:= TList.Create;
  308.   if FileName <> '' then
  309.     LoadFromFile;
  310. end;
  311. destructor TVersionList.Destroy;
  312. begin
  313.   if FFileName <> '' then
  314.     SaveToFile;
  315.   Clear;
  316.   FVersions.Free;
  317.   inherited;
  318. end;
  319. function TVersionList.GetCount: Integer;
  320. begin
  321.   Result:= FVersions.Count;
  322. end;
  323. function TVersionList.GetItems(Index: Integer): PVersionInfo;
  324. begin
  325.   Result:= PVersionInfo(FVersions[Index]);
  326. end;
  327. function TVersionList.GetVersions(FileName: string): TVersion;
  328. var
  329.   Index: Integer;
  330. begin
  331.   Index:= IndexOf(FileName);
  332.   if Index = -1 then
  333.     raise Exception.Create('未找到文件版本信息!');
  334.   Result:= Items[Index]^.Version;
  335. end;
  336. function TVersionList.IndexOf(FileName: string): Integer;
  337. var
  338.   I: Integer;
  339. begin
  340.   Result:= -1;
  341.   for I:= 0 to FVersions.Count - 1 do
  342.     if SameText(PVersionInfo(FVersions[I])^.FileName, FileName) then
  343.     begin
  344.       Result:= I;
  345.       Break;
  346.     end;
  347. end;
  348. procedure TVersionList.LoadFromFile;
  349. var
  350.   Stream: TStream;
  351.   I, C: Integer;
  352.   szFileName, szVersion: string;
  353. begin
  354.   Clear;
  355.   if not FileExists(FFileName) then Exit;
  356.   Stream:= TFileStream.Create(FFileName, fmOpenRead);
  357.   try
  358.     C:= StreamReadInteger(Stream);
  359.     for I:= 0 to C - 1 do
  360.     begin
  361.       szFileName:= StreamReadString(Stream);
  362.       szVersion:= StreamReadString(Stream);
  363.       Add(szFileName, szVersion);
  364.     end;
  365.   finally
  366.     Stream.Free;
  367.   end;
  368. end;
  369. procedure TVersionList.SaveToFile;
  370. var
  371.   Stream: TStream;
  372.   I: Integer;
  373. begin
  374.   Stream:= TFileStream.Create(FFileName, fmCreate);
  375.   try
  376.     StreamWriteInteger(Stream, Count);
  377.     for I:= 0 to Count - 1 do
  378.     begin
  379.       StreamWriteString(Stream, Items[I]^.FileName);
  380.       StreamWriteString(Stream, Items[I].Version);
  381.     end;
  382.   finally
  383.     Stream.Free;
  384.   end;
  385. end;
  386. procedure TVersionList.SetVersions(FileName: string; const Value: TVersion);
  387. var
  388.   Index: Integer;
  389. begin
  390.   Index:= IndexOf(FileName);
  391.   if Index = -1 then
  392.     raise Exception.Create('未找到文件版本信息!');
  393.   Items[Index]^.Version:= Value;
  394. end;
  395. procedure TVersionList.Update(FileName, Version: string);
  396. var
  397.   Index: Integer;
  398. begin
  399.   Index:= IndexOf(FileName);
  400.   if Index <> -1 then
  401.     Items[Index]^.Version:= Version
  402.   else
  403.     Add(FileName, Version);
  404. end;
  405. function TResTree.AddFile(ParentNode: TResNode; AFileName: string): TResNode;
  406. var
  407.   pInfo: PResInfo;
  408.   srFile: TSearchRec;
  409.   APath: string;
  410. begin
  411.   FRootDir:= ParentNode.Tree.RootNode.Text;
  412.   APath:= ExtractFilePath(AFileName);
  413.   FindFirst(AFileName, faAnyFile + faHidden + faSysFile + faReadOnly, srFile);
  414.   try
  415.     New(pInfo);
  416.     with pInfo^ do
  417.     begin
  418.       FileName:= srFile.Name;
  419.       Description:= GetFileDescription(srFile.Name);
  420.       FileSize:= srFile.Size;
  421.       FileAttr:= srFile.Attr;
  422.       ModifyTime:= FileDateToDateTime(FileAge(APath + srFile.Name));
  423.       Version:= GetFileVersion(APath + srFile.Name);
  424.       ResType:= rtFile;
  425.       DownloadURL:= ExtractRelativePath(APath + srFile.Name);
  426.     end;
  427.     Result:= TResNode(AddNode(ParentNode, pInfo^.FileName));
  428.     Result.Data:= pInfo;
  429.   finally
  430.     FindClose(srFile);
  431.   end;
  432. end;
  433. end.