Delphi 检查Zip文件的有效性

Delphi 检查Zip文件的有效性,delphi,Delphi,当我尝试检查zip文件的有效性时,会出现一个异常,即进程无法访问该文件,因为另一个进程正在使用该文件,但Open1中的代码仍然存在。单击打开zip文件时没有问题。有效点击有什么问题吗 procedure TForm1.Valid1Click(Sender: TObject); { Is the zip file valid. } var iZipFile: TZipFile; iZipFilename: string; iValid: Boolean; begin Screen.

当我尝试检查zip文件的有效性时,会出现一个异常,即进程无法访问该文件,因为另一个进程正在使用该文件,但Open1中的代码仍然存在。单击打开zip文件时没有问题。有效点击有什么问题吗

procedure TForm1.Valid1Click(Sender: TObject);
{ Is the zip file valid. }
var
  iZipFile: TZipFile;
  iZipFilename: string;
  iValid: Boolean;
begin
  Screen.Cursor := crHourGlass;
  try
    { Create the TZipFile Class }
    iZipFile := TZipFile.Create;
    try
      if FileExists(ZipFilename1.Text) then
      begin
         iZipFilename := ZipFilename1.Text;
         { Open zip file for reading }
         iZipFile.Open(iZipFilename, zmRead);
         iValid := iZipFile.IsValid(iZipFilename);
         if iValid then
           MessageBox(0, 'The zip file is valid.', 'Check Zip File',
             MB_ICONINFORMATION or MB_OK)
         else
           MessageBox(0, 'The zip file is NOT valid.', 'Check Zip File',
              MB_ICONWARNING or MB_OK);
         end
         else
            begin
              MessageBox(0, 'The zip file does not exist.', 'Warning',
                MB_ICONWARNING or MB_OK);
            end;
         { Close the zip file }
         iZipFile.Close;
       finally
         iZipFile.Free;
       end;
     finally
        Screen.Cursor := crDefault;
     end;
end;

procedure TForm1.Open1Click(Sender: TObject);
{ Open zip file. }
var
  i: integer;
  iZipFile: TZipFile;
  iFilename: string;
  iDateTime: TDateTime;
  iCompressedSize: cardinal;
  iUnCompressedSize: cardinal;
  iCRC32: cardinal;
  iCompressionMethod: word;
  iFileComment: string;
  iListItem: TlistItem;
begin
  if OpenDialog1.Execute then
  begin
    if FileExists(OpenDialog1.FileName) then
    begin
      iZipFile := TZipFile.Create;
      try
        ListView1.Items.Clear;
        ZipFilename1.Text := OpenDialog1.FileName;
        try
          iZipFile.Open(ZipFilename1.Text, zmReadWrite);
          for i := 0 to iZipFile.FileCount - 1 do
          begin
            iFilename := iZipFile.FileNames[i];
            iListItem := ListView1.Items.Add;
            iListItem.Caption := iFilename;
            iDateTime := FileDateToDateTime
              (iZipFile.FileInfo[i].ModifiedDateTime);
            iListItem.SubItems.Add(DateTimeToStr(iDateTime)); { 0 }
            iCompressedSize := iZipFile.FileInfo[i].CompressedSize;
            iListItem.SubItems.Add(FormatByteSize(iCompressedSize)); { 1 }
            iUnCompressedSize := iZipFile.FileInfo[i].UncompressedSize;
            iListItem.SubItems.Add(FormatByteSize(iUnCompressedSize)); { 2 }
            iCRC32 := iZipFile.FileInfo[i].CRC32;
            iListItem.SubItems.Add(IntToStr(iCRC32)); { 3 }
            iCompressionMethod := iZipFile.FileInfo[i].CompressionMethod;
            iListItem.SubItems.Add
              (ZipCompressionToStr(iCompressionMethod)); { 4 }
            iFileComment := iZipFile.Comment;
            iListItem.SubItems.Add(iFileComment); { 5 }
          end;
          iZipFile.Close;
        except
          on E: Exception do
          begin
            ShowMessage(E.ClassName + #10#13 + E.Message);
          end;
        end;
      finally
        iZipFile.Free;
      end;
    end;
  end;

你把这些线绕错了方向:

iZipFile.Open(iZipFilename, zmRead);
iValid := iZipFile.IsValid(iZipFilename);
第一行锁定文件,因此第二行失败。在调用
Open
之前,您必须先调用
IsValid

话虽如此,由于您使用了
zmRead
,调用
IsValid
应该可以再次打开文件,因为调用
open
使用了
fmOpenRead
。因此,我怀疑您正在使用的Delphi版本中的ZIP文件代码或文件流代码中可能存在错误。尽管如此,在
Open
之前调用
IsValid
肯定会起作用

实际上,
IsValid
是一个类方法。你应该这样称呼它:

iValid := TZipFile.IsValid(iZipFilename);
最后也是一样,但它向代码的读者清楚地表明,方法调用并不依赖于实例的状态

事实上,我个人会干脆取消对
IsValid
的调用,直接调用
Open
。如果失败,我相信会发出一条有意义的错误信息


更新

看起来您根本不想打开该文件,只想检查其有效性。在这种情况下,您不需要实例,也不需要调用构造函数,只需调用一次
TZipFile.IsValid

procedure TForm1.Valid1Click(Sender: TObject);
begin
  Screen.Cursor := crHourGlass;
  try
    if FileExists(ZipFilename1.Text) then
    begin
      if TZipFile.IsValid(ZipFilename1.Text) then
        ...
  finally
    Screen.Cursor := crDefault;
  end;
end;

你把这些线绕错了方向:

iZipFile.Open(iZipFilename, zmRead);
iValid := iZipFile.IsValid(iZipFilename);
第一行锁定文件,因此第二行失败。在调用
Open
之前,您必须先调用
IsValid

话虽如此,由于您使用了
zmRead
,调用
IsValid
应该可以再次打开文件,因为调用
open
使用了
fmOpenRead
。因此,我怀疑您正在使用的Delphi版本中的ZIP文件代码或文件流代码中可能存在错误。尽管如此,在
Open
之前调用
IsValid
肯定会起作用

实际上,
IsValid
是一个类方法。你应该这样称呼它:

iValid := TZipFile.IsValid(iZipFilename);
最后也是一样,但它向代码的读者清楚地表明,方法调用并不依赖于实例的状态

事实上,我个人会干脆取消对
IsValid
的调用,直接调用
Open
。如果失败,我相信会发出一条有意义的错误信息


更新

看起来您根本不想打开该文件,只想检查其有效性。在这种情况下,您不需要实例,也不需要调用构造函数,只需调用一次
TZipFile.IsValid

procedure TForm1.Valid1Click(Sender: TObject);
begin
  Screen.Cursor := crHourGlass;
  try
    if FileExists(ZipFilename1.Text) then
    begin
      if TZipFile.IsValid(ZipFilename1.Text) then
        ...
  finally
    Screen.Cursor := crDefault;
  end;
end;

正如David Heffernan最初所说的:在TZipFile::Open(文件名,模式)之后应该可以使用isValid,因为人们希望以只读方式打开文件不会阻止其他人读取

当使用基于文件名的Open方法(存在另一个用于从TFileStream读取f的方法)时,它会在内部创建一个fileStream,虽然它指定了fmOpenRead,但在打开此流时不会设置共享模式

有关如何通过首先自己创建一个TFileStream(在其中明确指定共享模式)来避免这种情况的示例,请参阅本博客文章:

正如David Heffernan最初所说:在TZipFile::Open(文件名,模式)之后应该可以使用isValid,因为人们希望以只读方式打开文件不会阻止其他人读取

当使用基于文件名的Open方法(存在另一个用于从TFileStream读取f的方法)时,它会在内部创建一个fileStream,虽然它指定了fmOpenRead,但在打开此流时不会设置共享模式

有关如何通过首先自己创建一个TFileStream(在其中明确指定共享模式)来避免这种情况的示例,请参阅本博客文章:

它开始看起来似乎根本不需要open,甚至可能需要iZipFile:=TZipFile.Create;?啊,我以为你想看文件。如果您只想检查有效性,那么您根本不需要实例。它开始看起来似乎根本不需要open,甚至可能不需要iZipFile:=TZipFile.Create;?啊,我以为你想看文件。如果您只想检查有效性,那么根本不需要实例。