DiskList.PAS
上传用户:psxgmh
上传日期:2013-04-08
资源大小:15112k
文件大小:17k
源码类别:

Delphi/CppBuilder

开发平台:

Delphi

  1. unit DiskList;
  2. interface
  3. uses
  4.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
  5.   Dialogs;
  6. {*****************************************
  7.   磁盘队列说明:
  8.   磁盘队列的前[0..511]字节作为磁盘队列的头信息区,
  9. [0..1]为类型区、[2..5]为头指针、[6..9]为尾指针、
  10. [10..13]为此磁盘队列文件的大小。从512开始为数据区域,
  11. 每一个数据区的前四个字节为该数据区的大小。
  12. ******************************************}
  13. const divaccount = 100;
  14. type
  15.   //定义磁盘队列
  16.   TcommQueue = class(Tcomponent)
  17.   private
  18.     FFilename: string; //磁盘文件名
  19.     Ffilesize: longint; //文件的大小
  20.     Ffrontpointer, Frearpointer: longint; //文件的前后指针
  21.     Fscroll: char; //是否回绕
  22.     hMutex: THandle; //互斥句柄
  23.     Q: file;
  24.   published
  25.     property Filename: string read FFilename write Ffilename;
  26.     property filesize: longint read FFilesize write Ffilesize;
  27.     property frontpointer: longint read Ffrontpointer write Ffrontpointer;
  28.     property rearpointer: longint read Frearpointer write Frearpointer;
  29.   private
  30.    //获取磁盘文件所剩空间;
  31.     function getleftsize(var leftsize: integer): integer;
  32.      //读取头指针信息;
  33.     function readheadfront: integer;
  34.     //读取尾指针信息;
  35.     function readheadrear: integer;
  36.     //读取文件指定的最大尺寸;
  37.     function readFileSize: integer;
  38.      //读取是否回绕字符值
  39.     function readscroll: integer;
  40.     //写入头指针信息
  41.     function writeheadfront(const frontposition: longint): integer;
  42.     //写入尾指针信息
  43.     function writeheadrear(const rearposition: longint): integer;
  44.     //写入是否回绕字符值
  45.     function writescroll(const myscroll: char): integer;
  46.     //写入对应的一条队列的大小;
  47.     function writebuffersize(const position: longint; const buffersize: longint): integer;
  48.     //从磁盘文件读出队列,保存为流
  49.     function readStream(var aStream: TMemoryStream): integer;
  50.     //将流写入磁盘队列
  51.     function writeStream(aStream: TMemoryStream): integer;
  52.     // 加一处理
  53.     function addone(var position: longint): longint;
  54.   public
  55.     //打开磁盘文件;
  56.     function Open(const Myfilename: string; const MyFileSize: longint): integer;
  57.     //关闭队列
  58.     procedure close;
  59.     //判断磁盘队列是否为空;1代表True ,0代表假
  60.     function empty: integer;
  61.     //读取磁盘队列一条内容
  62.     function readQueue(var buffer; var size: longint): integer;
  63.     //向磁盘队列插入一条内容
  64.     function writequeue(const buffer; const size: integer): integer;
  65.     //读入对应的一条队列的大小;
  66.     function readbuffersize(const position: longint; var buffsize: longint): longint;
  67.   end;
  68. implementation
  69. //根据磁盘名得到磁盘的对应磁盘号
  70. function GetDriveBytebyName(Filename: string): byte;
  71. var
  72.   xdrive: string;
  73.   xdrivechar: char;
  74.   xdrivebyte: byte;
  75. begin
  76.   if length(filename) > 0 then
  77.   begin
  78.     xdrive := copy(filename, 1, 1);
  79.     xdrive := uppercase(xdrive);
  80.     xdrivechar := xdrive[1];
  81.     xdrivebyte := ord('A');
  82.     result := (ord(xdrivechar) - xdrivebyte) + 1;
  83.   end;
  84. end;
  85. //打开磁盘文件,并初始化文件
  86. function TcommQueue.open(const Myfilename: string; const MyFileSize: longint): integer;
  87. {---------
  88.   返回值为-1   打开文件出错或写出错
  89.           -3   磁盘空间不足
  90.           -4  文件只读
  91. }
  92. var
  93.   buffer: array[0..511] of char;
  94.   writeaccount: integer;
  95.   i: integer;
  96.   drive: byte;
  97.   diskfreesize: int64;
  98.   xx: string;
  99.   xxx: char;
  100. begin
  101.   FFilename := MyFilename;
  102.   FFileSize := MyFileSize;
  103.   result := 1;
  104.   Assignfile(Q, FFilename);
  105.   //如果文件存在,打开
  106.   if fileexists(FFilename) then
  107.   begin
  108.     if fileisreadonly(Ffilename) then
  109.     begin
  110.       result := -4; //文件为只读
  111.       exit;
  112.     end;
  113.     try
  114.       Reset(Q, 1);
  115.       //从磁盘队列读取磁盘队列的头、尾指针、文件大小、是否回绕。
  116.       readheadfront;
  117.       readheadrear;
  118.       readFileSize;
  119.       readscroll;
  120.     except
  121.       result := -1; //代表打开文件错误
  122.     end;
  123.   end
  124.   else
  125.   //不存在,创建
  126.   begin
  127.     try
  128.       //判断磁盘队列
  129.       drive := getDriveByteByName(Ffilename);
  130.       diskfreesize := diskfree(drive);
  131.       if diskfreesize <= FFileSize then
  132.       begin
  133.         result := -3; //磁盘空间不足
  134.         exit;
  135.       end;
  136.       //初始化队列
  137.       Ffrontpointer := 512;
  138.       Frearpointer := 512;
  139.       Fscroll := 'N';
  140.       buffer[0] := 'A';
  141.       buffer[1] := 'A';
  142.       move(Ffrontpointer, buffer[2], 4);
  143.       move(Frearpointer, buffer[6], 4);
  144.       move(FFileSize, buffer[10], 4);
  145.       buffer[14] := 'N';
  146.       fillchar(buffer[15], 497, '0');
  147.       rewrite(Q, 1);
  148.       blockwrite(Q, buffer, 512, writeaccount);
  149.       if writeaccount <> 512 then
  150.       begin
  151.         result := -1; //代表写入数据有误
  152.         exit;
  153.       end;
  154.       for i := 1 to FFileSize div 512 do
  155.       begin
  156.         fillchar(buffer[0], 512, '0');
  157.         blockwrite(Q, buffer, 512, writeaccount);
  158.         if writeaccount <> 512 then
  159.         begin
  160.           result := -1; //代表写入数据有误
  161.           exit;
  162.         end;
  163.       end;
  164.       fillchar(buffer[0], FFileSize mod 512, '0');
  165.       blockwrite(Q, buffer, FFileSize mod 512, writeaccount);
  166.       if writeaccount <> FFileSize mod 512 then
  167.       begin
  168.         result := -1; //代表写入数据有误
  169.       end;
  170.     except
  171.       result := -1;
  172.     end;
  173.     reset(Q, 1);
  174.   end;
  175.   //创建互斥句柄
  176.   hMutex := CreateMutex(nil, false, nil);
  177. end;
  178. //关闭队列
  179. procedure TcommQueue.close;
  180. begin
  181.   closefile(Q);
  182.   closeHandle(hMutex);
  183. end;
  184. //判断磁盘队列是否为空
  185. function TcommQueue.empty: integer;
  186. begin
  187.   result := 0;
  188.   if Fscroll = 'N' then
  189.   begin
  190.     if Frearpointer = Ffrontpointer then
  191.       result := 1
  192.     else
  193.       result := 0;
  194.   end;
  195. end;
  196. //获取磁盘文件所剩空间;
  197. function TcommQueue.getleftsize(var leftsize: longint): integer;
  198. begin
  199.   if Fscroll = 'N' then
  200.   begin
  201.     leftsize := (FFileSize - Frearpointer) + (Ffrontpointer - 512);
  202.   end
  203.   else
  204.   begin
  205.     leftsize := Ffrontpointer - frearpointer;
  206.   end;
  207. end;
  208. //读取头指针
  209. function TcommQueue.readheadfront: integer;
  210. var
  211.   readaccount: integer;
  212.   buffer: array[0..3] of char;
  213. begin
  214.   //移动磁盘文件指针到2的位置
  215.   seek(Q, 2);
  216.   blockread(Q, buffer, 4, readaccount);
  217.   move(buffer[0], Ffrontpointer, 4);
  218.   if readaccount <> 4 then
  219.     result := 0
  220.   else
  221.     result := 1
  222. end;
  223. //读取尾指针
  224. function TcommQueue.readheadrear: integer;
  225. var
  226.   readaccount: integer;
  227.   buffer: array[0..3] of char;
  228. begin
  229.   seek(Q, 6);
  230.   blockread(Q, buffer, 4, readaccount);
  231.   move(buffer[0], Frearpointer, 4);
  232.   if readaccount <> 4 then
  233.     result := 0
  234.   else
  235.     result := 1
  236. end;
  237. //读取文件指定的最大尺寸;
  238. function TcommQueue.readFileSize: integer;
  239. var
  240.   readaccount: integer;
  241.   buffer: array[0..3] of char;
  242. begin
  243.   seek(Q, 10);
  244.   blockread(Q, buffer, 4, readaccount);
  245.   move(buffer[0], FFileSize, 4);
  246.   if readaccount <> 4 then
  247.     result := 0
  248.   else
  249.     result := 1
  250. end;
  251. //写入头指针
  252. function TcommQueue.writeheadfront(const frontposition: longint): integer;
  253. var
  254.   buffer: array[0..3] of char;
  255.   writeaccount: integer;
  256. begin
  257.   move(frontposition, buffer[0], 4);
  258.   seek(Q, 2);
  259.   blockwrite(Q, buffer, 4, writeaccount);
  260.   if writeaccount <> 4 then
  261.   begin
  262.     result := -1;
  263.     exit;
  264.   end
  265.   else
  266.     result := 1;
  267.   Ffrontpointer := frontposition;
  268. end;
  269. //写入尾指针
  270. function TcommQueue.writeheadrear(const rearposition: longint): integer;
  271. var
  272.   buffer: array[0..3] of char;
  273.   writeaccount: integer;
  274. begin
  275.   move(rearposition, buffer[0], 4);
  276.   seek(Q, 6);
  277.   blockwrite(Q, buffer, 4, writeaccount);
  278.   if writeaccount <> 4 then
  279.   begin
  280.     result := -1;
  281.     exit;
  282.   end
  283.   else
  284.     result := 1;
  285.   Frearpointer := rearposition;
  286. end;
  287. //读取对应的一条队列的大小;
  288. function TcommQueue.readbuffersize(const position: longint; var buffsize: longint): longint;
  289. var
  290.   buffer: array[0..3] of char;
  291.   I: integer;
  292.   readaccount: integer;
  293. begin
  294.   result := 1;
  295.   seek(Q, position);
  296.   //判断剩余大小是否大于4,如果小于4,则得分开读
  297.   if FFileSize - position < 4 then
  298.   begin
  299.     for i := 0 to (FFileSize - position - 1) do
  300.     begin
  301.       blockread(Q, buffer[i], 1, readaccount);
  302.       if readaccount <> 1 then
  303.       begin
  304.         result := -1;
  305.         exit;
  306.       end;
  307.     end;
  308.     seek(Q, 512);
  309.     for i := (FFileSize - position) to 3 do
  310.     begin
  311.       blockread(Q, buffer[i], 1, readaccount);
  312.       if readaccount <> 1 then
  313.       begin
  314.         result := -1;
  315.         exit;
  316.       end;
  317.     end;
  318.   end
  319.   else
  320.   begin
  321.     seek(Q, position);
  322.     blockread(Q, buffer, 4, readaccount);
  323.     if readaccount <> 4 then
  324.     begin
  325.       result := -1;
  326.       exit;
  327.     end;
  328.   end;
  329.   move(buffer[0], buffsize, 4);
  330. end;
  331. //写入对应的一条队列的大小;
  332. function TcommQueue.writebuffersize(const position: longint; const buffersize: longint): integer;
  333. var
  334.   buffer: array[0..3] of char;
  335.   I: integer;
  336.   writeaccount: longint;
  337. begin
  338.   result := -1;
  339.   seek(Q, position);
  340.   move(buffersize, buffer[0], 4);
  341.   //判断剩余大小是否大于4,如果小于4,则得分开写
  342.   if FFileSize - Frearpointer < 4 then
  343.   begin
  344.     for i := 0 to (FFileSize - Frearpointer - 1) do
  345.     begin
  346.       blockwrite(Q, buffer[i], 1, writeaccount);
  347.       if writeaccount <> 1 then
  348.       begin
  349.         result := -1;
  350.         exit;
  351.       end;
  352.     end;
  353.     seek(Q, 512);
  354.     for i := (FFileSize - Frearpointer) to 3 do
  355.     begin
  356.       blockwrite(Q, buffer[i], 1, writeaccount);
  357.       if writeaccount <> 1 then
  358.       begin
  359.         result := -1;
  360.         exit;
  361.       end;
  362.     end;
  363.   end
  364.   else
  365.   begin
  366.     blockwrite(Q, buffer, 4, writeaccount);
  367.     if writeaccount <> 4 then
  368.     begin
  369.       result := -1;
  370.       exit;
  371.     end;
  372.   end;
  373. end;
  374. //读取是否回绕字符值
  375. function TcommQueue.readscroll: integer; //读取是否回绕字符值
  376. var
  377.   readaccount: integer;
  378. begin
  379.   result := 1;
  380.   seek(Q, 14);
  381.   blockread(Q, Fscroll, 1, readaccount);
  382.   if readaccount <> 1 then
  383.     result := -1;
  384. end;
  385. //写入是否回绕字符值
  386. function TcommQueue.writescroll(const Myscroll: char): integer;
  387. var
  388.   writeaccount: integer;
  389. begin
  390.   result := 1;
  391.   seek(Q, 14);
  392.   blockwrite(Q, myscroll, 1, writeaccount);
  393.   if writeaccount <> 1 then
  394.   begin
  395.     result := -1;
  396.     exit;
  397.   end;
  398.   Fscroll := Myscroll;
  399. end;
  400. //从磁盘文件读出队列,保存为流
  401. function TCommQueue.readStream(var aStream: TMemoryStream): integer;
  402. var
  403.   buffer: array[1..divAccount] of char;
  404.   i: integer;
  405.   ActReadNum: Longint;
  406.   aleft: Longint;
  407.   bufferSize: longint;
  408. begin
  409.   result := 1;
  410.   //进入互斥,阻止其他线程访问
  411.   if waitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
  412.   begin
  413.     try
  414.       //判断底部剩余空间是否大于4,以判断是否分开读
  415.       if fFileSize - FfrontPointer - 4 > 0 then
  416.         aLeft := fFileSize - FfrontPointer - 4
  417.       else
  418.         aLeft := fFileSize - (FFrontPointer + 4 - fFileSize);
  419.       readbuffersize(Ffrontpointer, buffersize);
  420.       for i := 0 to buffersize div divAccount - 1 do
  421.       begin
  422.         if aLeft >= divAccount then
  423.         begin
  424.           blockRead(Q, buffer[1], divAccount, ActReadNum);
  425.           aStream.Write(buffer[1], divAccount);
  426.           aLeft := aLeft - divAccount;
  427.           if ActReadNum <> DivAccount then
  428.           begin
  429.             Result := -1;
  430.             exit;
  431.           end;
  432.         end
  433.         else
  434.         begin
  435.           blockRead(Q, buffer[1], aLeft, ActReadNum);
  436.           astream.Write(buffer[1], aLeft);
  437.           aLeft := fFileSize - ffrontPointer;
  438.           if ActReadNum <> aLeft then
  439.           begin
  440.             Result := -1;
  441.             exit;
  442.           end;
  443.           Seek(Q, 512);
  444.           blockRead(Q, buffer[1], divAccount - aLeft, ActReadNum);
  445.           astream.write(buffer[1], divAccount - aLeft);
  446.           aLeft := aLeft - (divAccount - aLeft);
  447.           if ActReadNum <> divAccount - aLeft then
  448.           begin
  449.             Result := -1;
  450.             exit;
  451.           end;
  452.         end;
  453.       end;
  454.     //如果还有剩余
  455.       if bufferSize mod divAccount <> 0 then
  456.       begin
  457.         if aleft >= bufferSize mod divAccount then
  458.         begin
  459.           blockRead(Q, buffer[1], bufferSize mod divAccount, actReadNum);
  460.           aStream.Write(buffer, bufferSize mod divAccount);
  461.           if ActReadNum <> DivAccount then
  462.           begin
  463.             Result := -1;
  464.             exit;
  465.           end;
  466.         end
  467.         else
  468.         begin
  469.           blockRead(Q, buffer[1], aLeft, actReadNum);
  470.           aStream.Write(buffer[1], aLeft);
  471.           if ActReadNum <> DivAccount then
  472.           begin
  473.             Result := -1;
  474.             exit;
  475.           end;
  476.           Seek(Q, 512);
  477.           blockRead(Q, buffer[1], bufferSize mod divAccount - aleft, actReadNum);
  478.           aStream.Write(buffer[1], bufferSize mod divAccount - aleft);
  479.           if ActReadNum <> DivAccount then
  480.           begin
  481.             Result := -1;
  482.             exit;
  483.           end;
  484.         end;
  485.       end;
  486.     finally
  487.       //离开互斥状态
  488.       releaseMutex(hMutex);
  489.     end;
  490.   end;
  491. end;
  492. //读取磁盘队列一条内容
  493. function TcommQueue.readqueue(var buffer; var size: longint): integer;
  494. var
  495.   recvstream: TmemoryStream;
  496. begin
  497.   result := 1;
  498.   if empty = 1 then
  499.   begin
  500.     result := -1; //队列已空
  501.     exit;
  502.   end;
  503.   //创建接收的内存流
  504.   recvStream := TMemoryStream.Create;
  505.   //调用ReadStream,从磁盘队列读出一条内容
  506.   readStream(recvStream);
  507.   recvStream.Seek(0, 0);
  508.   //将流写入Buffer
  509.   recvStream.Read(Buffer, recvStream.Size);
  510.   size := recvStream.Size;
  511.   //指针向后移动一位
  512.   Ffrontpointer := addone(Ffrontpointer);
  513.   writeheadfront(Ffrontpointer);
  514. end;
  515. //将流写入磁盘队列
  516. function TCommQueue.writeStream(aStream: TMemoryStream): integer;
  517. var
  518.   buffer: array[1..divAccount] of char;
  519.   i: integer;
  520.   ActWriteNum: Longint;
  521.   aleft: Longint;
  522. begin
  523.   Result := 1;
  524.   //进入互斥,阻止其他线程访问
  525.   if waitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
  526.   begin
  527.     try
  528.       //判断底部剩余空间是否大于4,以判断是否分开写
  529.       if fFileSize - Frearpointer - 4 > 0 then
  530.         aLeft := fFileSize - Frearpointer - 4
  531.       else
  532.         aLeft := fFileSize - (FrearPointer + 4 - fFileSize);
  533.       aStream.Seek(0, 0);
  534.       for i := 0 to aStream.Size div divAccount - 1 do
  535.       begin
  536.         if aLeft >= divAccount then
  537.         begin
  538.           aStream.Read(buffer[1], divAccount);
  539.           blockWrite(Q, buffer[1], divAccount, ActWriteNum);
  540.           aLeft := aLeft - divAccount;
  541.           if ActWriteNum <> DivAccount then
  542.           begin
  543.             Result := -1;
  544.             exit;
  545.           end;
  546.         end
  547.         else
  548.         begin
  549.           astream.Read(buffer[1], aLeft);
  550.           blockWrite(Q, buffer[1], aLeft, ActWriteNum);
  551.           aLeft := fFileSize - ffrontPointer;
  552.           if ActWriteNum <> aLeft then
  553.           begin
  554.             Result := -1;
  555.             exit;
  556.           end;
  557.           Seek(Q, 512);
  558.           astream.Read(buffer[1], divAccount - aLeft);
  559.           blockWrite(Q, buffer[1], divAccount - aLeft, ActWriteNum);
  560.           aLeft := aLeft - (divAccount - aLeft);
  561.           if ActWriteNum <> divAccount - aLeft then
  562.           begin
  563.             Result := -1;
  564.             exit;
  565.           end;
  566.         end;
  567.       end;
  568.     //如果还有剩余
  569.       if aStream.Size mod divAccount <> 0 then
  570.       begin
  571.         if aleft >= aStream.Size mod divAccount then
  572.         begin
  573.           aStream.read(buffer[1], aStream.Size mod divAccount);
  574.           blockWrite(Q, buffer[1], aStream.Size mod divAccount, actWriteNum);
  575.           if ActWriteNum <> DivAccount then
  576.           begin
  577.             Result := -1;
  578.             exit;
  579.           end;
  580.         end
  581.         else
  582.         begin
  583.           aStream.Read(buffer[1], aLeft);
  584.           blockWrite(Q, buffer[1], aLeft, actWriteNum);
  585.           if ActWriteNum <> DivAccount then
  586.           begin
  587.             Result := -1;
  588.             exit;
  589.           end;
  590.           Seek(Q, 512);
  591.           aStream.Read(buffer[1], aStream.Size mod divAccount - aleft);
  592.           blockWrite(Q, buffer[1], aStream.Size mod divAccount - aleft, actWriteNum);
  593.           if ActWriteNum <> DivAccount then
  594.           begin
  595.             Result := -1;
  596.             exit;
  597.           end;
  598.         end;
  599.       end;
  600.     finally
  601.       //离开互斥
  602.       releaseMutex(hMutex);
  603.     end;
  604.   end;
  605. end;
  606. //向磁盘队列插入一条内容
  607. function TcommQueue.writequeue(const Buffer; const size: integer): integer;
  608. var
  609.   SendStream: Tmemorystream;
  610.   leftsize: longint;
  611. begin
  612.   result := 1; //代表写成功
  613.   getleftsize(leftsize);
  614.   if leftsize < size + 4 then //判断剩余空间是否够
  615.   begin
  616.     result := -1; //剩余空间;
  617.     exit;
  618.   end;
  619.   try
  620.     //创建内存流
  621.     sendStream := Tmemorystream.Create;
  622.     //将buffer写入到流中
  623.     sendStream.WriteBuffer(buffer, size);
  624.     sendStream.Seek(0, sofrombeginning);
  625.     //写入数据区大小
  626.     WriteBufferSize(Frearpointer, size);
  627.     //将流写入磁盘队列
  628.     writeStream(sendStream);
  629.     //将尾指针相后移
  630.     Frearpointer := addone(Frearpointer);
  631.     writeheadrear(Frearpointer);
  632.   finally
  633.     sendStream.Free;
  634.   end;
  635. end;
  636. //将指针向下移
  637. function TcommQueue.addone(var position: longint): longint;
  638. var
  639.   buffersize: longint;
  640.   nextposition: longint;
  641. begin
  642.   readFileSize;
  643.   readbuffersize(position, buffersize);
  644.   nextposition := position + 4 + buffersize;
  645.   if nextposition > FFileSize then
  646.   begin
  647.     if Fscroll = 'Y' then
  648.       Fscroll := 'N'
  649.     else
  650.       Fscroll := 'Y';
  651.     writescroll(Fscroll);
  652.     result := (position + 4 + buffersize) mod FFileSize + 512;
  653.   end
  654.   else
  655.     result := position + 4 + buffersize;
  656. end;
  657. end.