D7Zip file list

4

I'm using D7Zip ( link ) to extract files, and would like to get the entire list of files of the compressed file. In the documentation, I found this:

with CreateInArchive(CLSID_CFormat7z) do
 begin
   OpenFile('c:\test.7z');
   for i := 0 to NumberOfItems - 1 do
    if not ItemIsFolder[i] then
      Writeln(ItemPath[i]);
 end;

I left it like this:

with CreateInArchive(CLSID_CFormat7z) do
 begin
   OpenFile('c:\test.7z');
   for i := 0 to NumberOfItems - 1 do
    if not ItemIsFolder[i] then
      FilesInZ[i] := ItemPath[i];
 end;

Of course, before I stated:

FilesInZ : array of string;

When running, the following error occurs:

Access Violation at address 004047B0 in module 'Launcher.exe'. Read of address 00000000.

The only error you give is a warning:

[Warning] LauncherUnit.pas(120): Variable 'filesinz' might not have been initialized

The line is this:

 FilesInZ[i] := ItemPath[i];

How could I resolve?

    
asked by anonymous 18.10.2014 / 19:32

1 answer

4

In Delphi / Pascal, dynamic arrays are declared without a number of "spaces" for initial use

var 
  vetor: array of string;

So if you try to add values to it before adding those "spaces" it will generate an access violation error.

It is like declaring an array of defined size and trying to access an item in a position that does not exist.

var
  vetor: array[5] of string;
begin
  vetor[5] := 'Olá mundo!'; // <-- isso gera erro.

In the example, although you have informed the vector with five "spaces" of use, you need to know that vectors start from zero. Therefore, this vector would have only the following positions:

vetor[0] := 'Olá mundo 1';
vetor[1] := 'Olá mundo 2';
vetor[2] := 'Olá mundo 3';
vetor[3] := 'Olá mundo 4';
vetor[4] := 'Olá mundo 5';

The maximum position is 4, vetor[4] . The lowest is 0, vetor[0] , of course.

At first, for those who are learning, this can be a bit confusing but get used to it over time.

But what about the dynamic vectors?

As I said, dynamic vectors start with no spaces and to work with it you have two conditions:

  • Know exactly how much space you'll need;
  • Add as needed.
  • In most cases, the dynamic array is used when you do not know how many spaces will be used, and to do this it will be implemented as needed.

    For this, you need to know some resources to work with arrays in Delphi.

    Length () function: Used to find the current vector size

    var
      vetor: array of string;          
      tamanho: integer;
    begin
      tamanho := Length(vetor);  // <-- nesse momento o vetor possui 0 de tamanho, 
                                 // ou seja, nenhum espaço para uso
    
      SetLength(vetor, Length(vetor) + 1);
    
      tamanho := Length(vetor); // <-- nesse momento o vetor possui 1 de tamanho,
                                // ou seja, 1 espaço para uso, índice 0 (zero) vetor[0].
    

    High () function: Used to know the largest vector position

    var
      vetor: array of string;
      max: integer;
    begin
      max := High(vetor); // <-- nesse momento a maior posição do vetor é -1,
                          // ou seja, ainda não há posição, então retorna -1.
    
      SetLength(vetor, Length(vetor) + 1);
    
      max := High(vetor); // <-- nesse momento a maior posição do vetor é 0 (zero),
                          // ou seja, o vetor possui uma posição para uso, logo essa 
                          // posição é a 0 (zero)
    
      SetLength(vetor, Length(vetor) + 1);
    
      max := High(vetor); // <-- agora, a posição máxima é 1
    

    SetLength () function: Used to set size in dynamic vectors

    It has been used in the previous examples and I will describe it here:

  • The first parameter is the vector itself that you want to change the size of it.
  • The second parameter is the size you want to set for the vector.
  • So, to always add an extra position in the vector you use Length() to get its current size and then add 1 more.

    SetLength(vetor, Length(vetor) - 1);
    

    With the same function you can remove all positions of the vector

    SetLength(vetor, 0);
    

    Finally,

    In your case, you would advise doing the following:

    with CreateInArchive(CLSID_CFormat7z) do
    begin
      OpenFile('c:\test.7z');
      for i := 0 to NumberOfItems - 1 do
      begin
        if not ItemIsFolder[i] then
        begin
          SetLength(FilesInZ, Length(FilesInZ) + 1);
          FilesInZ[High(FilesInZ)] := ItemPath[i];
        end;
      end;
    end;
    

    Notice that I add a position: SetLength(FilesInZ, Length(FilesInZ) + 1);

    Then I add the value in the last position it has: FilesInZ[High(FilesInZ)] := ItemPath[i];
    I used High() to get the last position.

        
    19.10.2014 / 16:02