2017年7月7日 星期五

[ C / C++] 讀取任意目錄的 檔案名稱、路徑、濾特定副檔名

[ C / C++] 讀取任意目錄的 檔案名稱、路徑、濾特定副檔名

存取任意位置的目錄 - 第一版

這個可以讀取任意目錄位置下的所有檔案與目錄

  • 第一版是不能讀子目錄的,需要讀子目錄請繼續往下看
  • 如果需要過濾特定檔案,比如說圖片 *.jpg *.bmp 之類的
    改一下 extenName 擴展名的部分 *.jpg 就可以了
/*****************************************************************
Name : ReadFiles path
Date : 2017/05/22
By   : CharlotteHonG
Final: 2018/03/08
*****************************************************************/

#include <stdio.h>
#include <string.h>
#include <io.h>
#include <direct.h>

void getDirFile(const char* definePath, const char* extenName){
    char buff[1024];
    _chdir(definePath);
    unsigned long long hFile;
    struct _finddata_t fileName;
    hFile = _findfirst(extenName, &fileName);
    do {
        sprintf(buff, "%sprintf\\%s", definePath, fileName.name);
        printf("%s\n", buff);
    } while(hFile != -1 && _findnext(hFile, &fileName)==0);
}

int main(int argc, char const *argv[]){
    // 設置目錄與檔案類型
    const char* definePath = "C:\\";
    const char* extenName = "*.*";
    // 獲取目錄
    getDirFile(definePath, extenName);
    return 0;
}

第二版

原本第一版是不能讀取子目錄的,寫好第二版可以正常讀取了。

/*****************************************************************
Name : ReadFiles path
Date : 2017/05/22
By   : CharlotteHonG
Final: 2021/04/20
*****************************************************************/
#include <stdio.h>
#include <string.h>
#include <io.h>

void getFileList(const char* _dirPath, const char* extenName){
    struct _finddata_t file;
    intptr_t hFile;
    // 修正路徑
    char dirPath[256] = {0};
    if (_dirPath[strlen(_dirPath)-1]!='\\')
        sprintf(dirPath, "%s\\", _dirPath);
    else
        sprintf(dirPath, "%s", _dirPath);
    // 檢查路徑是否有效
    char buff[256] = {0};
    sprintf(buff, "%s%s", dirPath, extenName);
    if ((hFile = _findfirst(buff, &file)) == -1)
        perror("path error"), exit(1);
    int i=0;
    // 開始搜索
    do {
        // 避開當前目錄[.]和上一層目錄[..]
        if (!(strcmp(file.name, ".")) || !(strcmp(file.name, "..")))
            continue;
        // 子目錄
        if (file.attrib == _A_SUBDIR) {
            sprintf(buff, "%s%s", dirPath, file.name);
            getFileList(buff, extenName);
            // 檔案
        } else {
            sprintf(buff, "%s%s", dirPath, file.name);
            printf("%s\n", buff);
        }
    } while (_findnext(hFile, &file)==0);
}

int main(int argc, char const* argv[]) {
    const char* dirPath="Z:\\a";
    const char* extenName="*.*";
    getFileList(dirPath, extenName);
    return 0;
}

如果需要把檔名封裝到物件上,可以參考這一份檔案,是純C寫的。
https://gist.github.com/hunandy14/24a5e7690a18e6d3cf320e68d8ccc7fd




簡易的存取 main.c 當下的目錄文件

第二種方式是透過系統本身的命令列 dir 來讀取。

關於這個解決方案有更好的版本寫在這篇站內文
https://charlottehong.blogspot.com/2021/04/c-c.html

C++

/*****************************************************************
Name : ReadFiles path
Date : 2017/05/22
By   : CharlotteHonG
Final: 2017/05/24
*****************************************************************/
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char const *argv[]){
    system("dir /b /on >list.txt");
    fstream f("list.txt", ios::in);
    for(string s;f >> s;) {
        cout << s << endl;
    }
    return 0;
}

C語言

/*****************************************************************
Name : ReadFiles path
Date : 2017/05/22
By   : CharlotteHonG
Final: 2017/05/24
****************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[]){
    system("dir /b /on > list.txt");
    FILE *pFile = fopen("list.txt","r");
    for(char buf[128]; fgets(buf, 128, pFile) != NULL;){
        if(buf[strlen(buf)-1]='\n')
            buf[strlen(buf)-1] = '\0';
        printf("%s\n", buf);
    }
    return 0;
}

3 則留言:

  1. 我想請問有關C++部分
    C++ 的code是不是沒有路徑的部分
    而特定目錄的部分是list.txt? 還是記錄進去
    因為我執行此程式會抓我現在BCB安裝位置的所以檔案

    回覆刪除
    回覆
    1. 那你切換一下當前目錄吧,在windwos跑gcc預設會是main的位置

      多補這行,測試一下
      system("cd yourDir");

      如何看當前目錄(linux如果不行你在自己換一下)
      system("echo %cd%");

      刪除
    2. 測試一下,貌似不能直接存取有限制權限,我已經更新一份代碼了。
      可以重新整理後再看本文。

      刪除