4

アイスランドからこんにちは!

まず、グーグルとここの両方で検索しましたが、結果はありませんでした。

私は Delphi で書いており、Delphi で数年の経験があります (Pascal では 30 年以上)

私はここ数年、さまざまなファイル ユーティリティのプログラムを構築し、ほとんどすべてのアプリで FindFirst および FindNext 関数を使用してきました。今日、私が書いた古いファイル ユーティリティ プログラムを使用していたところ、100% 機能しないことがわかりました。

ディレクトリ名がおかしくなるまでは問題ありませんでした。話は、私がWampをインストールしていて、そこにあるいくつかのフォルダがこの奇妙な方法で命名されたということです.

As: "c:\wamp\apps\phpmyadmin3.4.5"
    "c:\wamp\apps\sqlbuddy1.3.3"
    "c:\wamp\apps\webgrind1.0 etc"

デバッグを行ったときに、Findnext がエラー 18 を返しただけであることがわかりました。これは、検索するファイルがなくなったときに FindNext が返すのと同じエラーです。

同じ結果で FindFirstFile と FindNextFile を試しました。これが長いファイル名に関係している場合は、API FindNextFileEx を試してみることを考えていますが、それほど楽観的ではありません..

また、これらのフォルダーの属性が 16 (hex10) ではなく 8208 (8192+16) であることに気付きましたが、たとえば属性を $00 でマスク (AND) できるため、この問題とは何の関係もありません。 FFなど

PROCEDURE TForm_Leit.Finna_Dir (Str_InnDir : STRING);
  VAR
    S_Rec1           : TSearchRec;
    Bo_Buid          : BOOLEAN;
BEGIN
  .
  .
  .
  //Find Dir part
  IF (FindFirst (Str_Inndir+'\*.', faDirectory, S_Rec1) = 0) THEN
  REPEAT
    Bo_Buid := FALSE;
    IF ((S_Rec1.Name = '.') OR (S_Rec1.Name = '..')) THEN
    REPEAT
      Bo_Buid := FindNext (S_Rec1) <> 0;
    UNTIL NOT((S_Rec1.Name = '.') OR (S_Rec1.Name = '..')) OR (Bo_BUid);

    IF NOT(Bo_Buid) THEN
      Finna_Dir (Str_Inndir+'\'+S_Rec1.Name); //Recursion

  UNTIL (FindNext (S_Rec1) <> 0);
END;
4

3 に答える 3

8

使用しているパターン ( '\*.') は、ピリオドのないファイル名とディレクトリ名にのみ一致します (これは、ファイルの拡張子がないことも意味します)。試してみてください:

IF (FindFirst (Str_Inndir+'\*', ...


少し詳しく説明すると、VCL の「Find..」関数は、ファイルまたはフォルダーを検索するかどうかを実際には気にしない、基礎となる API の「Find..」関数のラッパーです (渡すことができる「Attr」パラメーターsysutils.FindFirstは、 VCL によって提供される機能であり、VCL はフィルタリングによってのみ検索結果に影響を与えることができます)。したがって、' *.' パターンを使用した結果は、ファイルまたはフォルダーで異なりません。パターンがピリオドを含むファイル名を返すことができない場合、ピリオドを含むフォルダーも返すことができません。

パラメータの使用法は、dirコマンドと同じです。コマンドプロンプトから「..\apps」フォルダーに移動し、を発行する>dir *.と、質問のフォルダーがリストされません。

API のみを使用してファイルを列挙する次のサンプル コードで、さまざまな「パターン」を見て試してみて、さまざまなワイルド カードが検索結果にどのように影響するかを確認してください。

var
  Data: TWIN32FindData;

procedure ListFiles(const Path, Pattern: string; List: TStrings);

  function IsDot: Boolean;
  begin
    Result := (string(Data.cFileName) = '.') or (Data.cFileName = '..');
  end;

  function IsDirectory: Boolean;
  begin
    Result := Bool(Data.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY);
  end;

  procedure PutFileName;
  begin
    if not IsDot then begin
      if IsDirectory then
        List.Add(Path + '\' + Data.cFileName + ' <dir>')
      else
        List.Add(Path + '\' + Data.cFileName);                                  //'
    end;
  end;

var
  FindHandle: THandle;
begin
  FindHandle := FindFirstFile(PChar(Path + Pattern), Data);
  if FindHandle <> INVALID_HANDLE_VALUE then
    try
      PutFileName;

      while FindNextFile(FindHandle, Data) do begin
        PutFileName;
        if (not IsDot) and IsDirectory then
          ListFiles(Path + '\' + Data.cFileName, Pattern, List);                //'
      end;

    finally
      windows.FindClose(FindHandle);
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  Pattern = '\*';
begin
  Memo1.Clear;
  ListFiles('..sometestdirectory..', Pattern, Memo1.Lines);
end;
于 2012-04-23T11:25:20.687 に答える
0

この問題を回避するには、別の方法があります。

1/ 完全なフィルターを使用する (更新はフォルダー用です)

  FA_ALL_FILES_EX = faNormalFile +
    faReadOnly + faHidden + faSysFile + faArchive + faTemporary + faSparseFile
    + faReparsePoint + faCompressed + faOffline + faNotContentIndexed + faEncrypted;  

  // $80 must be added because if the file's archive attribute is not set,
  // then FindFirst return [FindoInfo.Attr = 128]  ...

2/ Delphi2009+ ユニット IOUtils の最新の関数を使用します: IOUtils.TDirectory.GetDirectories() http://docwiki.embarcadero.com/VCL/XE2/en/IOUtils.TDirectory.GetDirectories

于 2012-04-23T07:11:33.363 に答える
0

faAnyFile 定数を使用していますか? これは間違っており、必要な値がすべて含まれていません。$FFFF の値を持つ新しい定数を定義 (および使用) します。

于 2012-04-23T07:14:34.163 に答える