web-dev-qa-db-ja.com

Windows APIを使用してディレクトリ内のファイルを一覧表示する方法は?

私はこのコードを持っていて、その内容ではなくディレクトリ自体を含むフォルダを表示します。内容を表示したい。 boost :: filesystemを使用したくない。

どうすればこれを解決できますか?

コード:

#include <windows.h>
#include <iostream>

int main()
{
    WIN32_FIND_DATA data;
    HANDLE hFind = FindFirstFile("C:\\semester2", &data);      // DIRECTORY

    if ( hFind != INVALID_HANDLE_VALUE ) {
        do {
            std::cout << data.cFileName << std::endl;
        } while (FindNextFile(hFind, &data));
        FindClose(hFind);
    }
}

出力:

semester2
12
John Escobia
HANDLE hFind = FindFirstFile("C:\\semester2", &data);       // DIRECTORY

あなたが求めていたので、あなたはディレクトリを得ました。ファイルが必要な場合は、次のように要求してください。

HANDLE hFind = FindFirstFile("C:\\semester2\\*", &data);  // FILES

(代わりに*.*必要に応じて、ただし、これは下位互換性のためのハックのためにのみ機能すると思われるため、おそらく回避する必要があります。コメントとRbMmの回答を参照してください。)

13
Harry Johnston

"*.*""*"について、いくつか注意点を示します。これらのファイラーは等しくありません。

somefileおよびsomefile.の2つの異なるファイルがフォルダーに存在できます。

低レベルのAPI ZwQueryDirectoryFile"*.*"とともに検索式として使用した場合(これは10番目のパラメーターです-FileName [in, optional])-somefile.のみを取得します。しかし、"*"を使用した場合、somefilesomefile.の両方のファイルが取得されます。

FindFirstFile("C:\\semester2\\*.*", &data);を試してみると、somefilesomefile.の両方のファイルが返されることがわかります。したがって、ここで"*.*""*"は同じ効果があります-使用法に違いはありません。

なぜこれが起こるのですか? FindFirstFileEx内のkernelbasekernel32)内で"*.*"マスクを特別にチェックし、それがtrueの場合は、"""*"と同じ効果を持つ空の名前)に置き換えます。

これは、ユーザーが正しい"*.*"ではなく"*"を渡す場合の非常に一般的なエラーを修正するため、およびレガシーコードとの下位互換性のために行われたと思います。

.および..は、ディスクに格納されるため、実際にはディレクトリの一部ではありませんが、Win32 APIによって追加されます。

本当じゃない。

  • FATスタイルのファイルシステムの場合、これは実際には2つの最初のエントリとしてFATディレクトリに格納されます。
  • NTFSにはそのようなエントリはありませんが、NTFS.sysがマスク内にある場合は、この2つのエントリを人工的に追加します。

したがって、これはWin32 APIレベルではなく、ドライバーレベルでカーネルで行われます。

結論として、"*.*"はWin32 APIで正しく機能するようになりましたが、ここでは"*"を使用するのが正しい方法です。
"*.*"ZwQueryDirectoryFile apiと間違えます。

6
RbMm

ハリーズアンサーは、実際には、目的のフォルダー"C:\\semester2"に拡張子を持つファイルとフォルダーを生成します。

たとえば、"C:\\semester2\\math.course"という名前のフォルダがある場合、上記の例でも見つかります。さらに、"C:\\semester2\\math_scores"という名前のファイルがある場合(拡張子がないことに注意してください)、ファイルは見つかりません。

上記を考慮して、私は次の解決策を提案します:

HANDLE hFind = FindFirstFile("C:\\semester2\\*", &data); 

これにより、ディレクトリの下にあるアイテムのリスト全体がリストされます。ディレクトリのフィルタリングは、次の方法で実行できます。

if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// directory
}
else
{
// file
}

以下を参照に使用できます: FileAttributes constantsFIND_DATA structFindFirstFile API

0
papadp