首页 > 解决方案 > 将目录中的文件列表读入char数组

问题描述

我正在尝试使用一些字符串格式获取目录中的文件列表。目前,像这样。

#define BUFFER 4096

void ListDir(){
    WIN32_FIND_DATA data;
    HANDLE hFind;
    hFind = FindFirstFile("*", &data);
    char* dir = calloc(1, BUFFER);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        snprintf(dir, BUFFER, "RHPDIR<>%s\n", cDir());
        do {
            int len = strlen(dir);
          
            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                snprintf(dir + len, sizeof(dir) - len, "[DIRECTORY] %s\n", data.cFileName);
            }
            else {
                ULONGLONG FileSize = data.nFileSizeHigh;
                FileSize <<= sizeof(data.nFileSizeHigh) * 8;
                FileSize |= data.nFileSizeLow;
                snprintf(dir + len, sizeof(dir) - len, "[FILE] %s (%llu bytes)\n", data.cFileName, FileSize);
            }
        } while (FindNextFile(hFind, &data));

        sockSend(dir);
        if (dir)
        {
            free(dir);
        }
    }
}

问题是读取文件较多的目录,尤其是 System32 等大目录,缓冲区溢出。我知道我需要增加dir. 但我不明白我怎么能做到这一点。

目标:从任何目录获取包含所有文件和目录的缓冲区

我试过的:我觉得这是一个不好的方法,但我试过这个希望它能奏效。我制作了一个返回目录列表大小的函数,并使用该大小创建缓冲区。这适用于大多数目录,但仍然在 System32 目录中,我遇到了溢出。我也不得不为此扫描目录两次。:秒

int returnCurrentDirFilesize()
{
    WIN32_FIND_DATA data;
    HANDLE hFind;
    hFind = FindFirstFile("*", &data);
    int size = 0;
    char tmpbuf[BUFFER];
    if (hFind != INVALID_HANDLE_VALUE)
    {
        snprintf(tmpbuf, BUFFER, "RHPDIR<>%s\n", cDir());
        size += strlen(tmpbuf);

        do {
            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {

                memset(tmpbuf, '\0', BUFFER);
                snprintf(tmpbuf, BUFFER, "[DIRECTORY] %s\n", data.cFileName);
                size += strlen(tmpbuf);

            }
            else {
                ULONGLONG FileSize = data.nFileSizeHigh;
                FileSize <<= sizeof(data.nFileSizeHigh) * 8;
                FileSize |= data.nFileSizeLow;

                memset(tmpbuf, '\0', BUFFER);
                snprintf(tmpbuf, BUFFER, "[FILE] %s (%llu bytes)\n", data.cFileName, FileSize);
                size += strlen(tmpbuf);
            }
        } while (FindNextFile(hFind, &data));

        return size;
    }
}

void ListDir(){
    WIN32_FIND_DATA data;
    HANDLE hFind;
    hFind = FindFirstFile("*", &data);
    char* dir = calloc(1, BUFFER);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        snprintf(dir, BUFFER, "RHPDIR<>%s\n", cDir());
        do {
            int len = strlen(dir);
          
            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                snprintf(dir + len, sizeof(dir) - len, "[DIRECTORY] %s\n", data.cFileName);
            }
            else {
                ULONGLONG FileSize = data.nFileSizeHigh;
                FileSize <<= sizeof(data.nFileSizeHigh) * 8;
                FileSize |= data.nFileSizeLow;
                snprintf(dir + len, sizeof(dir) - len, "[FILE] %s (%llu bytes)\n", data.cFileName, FileSize);
            }
        } while (FindNextFile(hFind, &data));

        sockSend(dir);
        if (dir)
        {
            free(dir);
        }
    }
}

标签: cwindows

解决方案


您可以使用 realloc 函数来完成此操作。我在下面编辑了您的代码,以向您展示如何使用以完成此操作

#define BUFFER 4096

void ListDir() 
{
    WIN32_FIND_DATAA data;
    HANDLE hFind;
    hFind = FindFirstFileA("C:\\windows\\system32\\*", &data);
    char* dir = calloc(BUFFER, sizeof(char));
    size_t dirSize = BUFFER;
    size_t dirIndex = 0;
    if (hFind != INVALID_HANDLE_VALUE)
    {
        snprintf(dir, BUFFER, "RHPDIR<>%s\n", "C:\\windows\\system32\\");
        dirIndex = strlen(dir);
        do {
            size_t currLineSize = 0;
            char currLine[MAX_PATH * 2] = { '\0' };

            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                snprintf(currLine, sizeof(currLine), "[DIRECTORY] %s\n", data.cFileName);
            }
            else {
                ULONGLONG FileSize = data.nFileSizeHigh;
                FileSize <<= sizeof(data.nFileSizeHigh) * 8;
                FileSize |= data.nFileSizeLow;
                snprintf(currLine, sizeof(currLine), "[FILE] %s (%llu bytes)\n", data.cFileName, FileSize);
            }

            // here we check if our memory is enough to store new line or not
            // if not, reallocate buffer with a new size
            currLineSize = strlen(currLine);
            if (dirIndex + currLineSize + sizeof(char) >= dirSize) {
                char* tmp = dir;
                dirSize += BUFFER;
                dir = realloc(dir, dirSize);
                if (dir == NULL) {
                    // allocation error
                    free(tmp);
                    exit(1);
                }
            }

            strcat_s(dir, dirSize, currLine);
            dirIndex += currLineSize;

        } while (FindNextFileA(hFind, &data));

        // sockSend(dir);
        printf("%s", dir);
        if (dir)
        {
            free(dir);
        }
    }
}

推荐阅读