【问题标题】:Browse a whole folder in C在 C 中浏览整个文件夹
【发布时间】:2021-09-13 19:26:23
【问题描述】:

我正在尝试列出文件夹的所有内容(包括子文件夹及其文件) 就像 Linux 中的 ls -R (我使用的是 Windows 10)

我已经有了这个带有“dirent.h”的基本代码

#include <stdio.h>
#include <dirent.h>

int main()
{
DIR *rep ;
struct dirent *file ;

rep = opendir ("c:\test") ;
if (rep != NULL)
{
while (file = readdir(rep))
printf ("%s\n", file->d_name) ;
(void) closedir (rep) ;
}
return 0;
}

它很好地列出了一个文件夹的内容,但不浏览子文件夹 例如它可以浏览整个硬盘 像 C:/

我不能使用 d_type 来检测内容是文件还是文件夹 因为windows的结构是:

struct dirent
{
    long        d_ino;      /* Always zero. */
    unsigned short  d_reclen;   /* Always zero. */
    unsigned short  d_namlen;   /* Length of name in d_name. */
    char        d_name[260]; /* [FILENAME_MAX] */ /* File name. */
};

所以我被困在这个问题上,如果有人有想法,甚至是代码


编译器:MinGW32 1.5.0

【问题讨论】:

  • 你应该stat每个目录的条目,看看它们是否是目录本身。然后递归地 readdir 任何目录条目。
  • 您的教程、书籍或课堂笔记对字符串中的反斜杠有何看法?
  • 使用stat(d_name) 获取信息。这是我们在添加d_type 之前必须做的事情
  • 在 Windows 上,我建议您使用原生 Windows 函数来遍历目录和文件,例如 FindFirstFileFindNextFile
  • 是什么阻止您迭代每个目录?你有这样做的算法吗?你知道如何分辨哪些条目是目录吗?您具体需要什么帮助?

标签: c windows


【解决方案1】:

这里是 Windows 目录列表的示例。

我使用 Microsoft Visual Studio Community 2019 进行构建。它作为 Unicode Windows 应用程序工作。也就是说,名称中包含非 ASCII 字符的文件和文件夹会得到正确处理。

为此,我使用了 Windows 典型的数据类型和函数:

char    -> WCHAR
strcpy  -> wcscpy
strcat  -> wcscat
strncmp -> wcsncmp
printf  -> wprintf

根据您使用的编译器,您可以使用标准数据类型和函数。 字符串常量以 L 为前缀,以指定 Unicode 字符串(16 位字符)。

主要功能是ScanDir,它带有起始目录和文件掩码。调用示例:

ScanDir(L"C:\\Users\\fpiette\\Documents", L"*.jpg");

ScanDir 将扫描指定文件夹中的所有文件,然后再次扫描所有目录,递归调用ScanDir。对于每个文件,都会显示大小和文件名(当然您可以显示其他属性,例如时间戳和属性)。对于每个目录,都会显示名称。

基本上,迭代目录是使用 Windows FindFirstFileFileNextFile 完成的。

源代码:

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>

BOOL ScanDir(
    WCHAR* srcDir,
    WCHAR* fileMask)
{
    WIN32_FIND_DATA fd;
    HANDLE fh;
    BOOL more;
    WCHAR fromDir[MAX_PATH];
    BOOL found;
    _int64 fileSize;

    wcscpy(fromDir, srcDir);
    wcscat(fromDir, L"\\");
    wcscat(fromDir, fileMask);

    // First step: process files in current dir
    fh = FindFirstFile(fromDir, &fd);
    more = fh != INVALID_HANDLE_VALUE;
    found = FALSE;
    while (more) {
        // Ignore directories in first step
        if (0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            if (!found) {
                // For the first file found, display the title
                found = TRUE;
                wprintf(L"\nDirectory %s\n\n", srcDir);
            }
            fileSize = ((_int64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow;
            // display file information
            wprintf(L"%12lld %s\n", fileSize, fd.cFileName);
        }
        more = FindNextFile(fh, &fd);
    }
    FindClose(fh);

    // Second step: recursively process subfolders
    wcscpy(fromDir, srcDir);
    wcscat(fromDir, L"\\*.*");
    fh = FindFirstFile(fromDir, &fd);
    more = fh != INVALID_HANDLE_VALUE;
    while (more) {
        // Ignore files in second step
        if (0 != (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            // We have a directory, process it recursively
            if (wcsncmp(fd.cFileName, L".", 2) &&    // Ignore current directory "."
                wcsncmp(fd.cFileName, L"..", 3)) {   // Ignore parent directory ".."
                wcscpy(fromDir, srcDir);
                wcscat(fromDir, L"\\");
                wcscat(fromDir, fd.cFileName);
                if (!ScanDir(fromDir, fileMask))
                    return 0;
            }
        }
        more = FindNextFile(fh, &fd);
    }
    FindClose(fh);

    return TRUE;
}

int main()
{
    // Change console output to unicode 16 bit (default is OEM)
    _setmode(_fileno(stdout), _O_U16TEXT);
    ScanDir(L"C:\\Users\\fpiette\\Documents", L"*.jpg");
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2013-01-07
    • 2010-11-21
    • 2020-09-05
    • 2012-06-22
    • 2011-08-14
    相关资源
    最近更新 更多