c++文件的讀寫

c++文件的讀寫

最近在一個圖片項目中使用到了用c++實現在給定目錄下的文件名的獲取。比如給定d:/data這樣一個目錄,返回在該目錄的所有文件名的完整路徑,本來難度並不是特別大,但是遇到的問題確實很奇葩,今故記錄下來給其他遇到類似問題的同學一點小幫助。在這個過程中,使用到了vs版本的,但是VS版本調試過程中出現了比較荒誕的錯誤,後面就嘗試使用Unix 版本下的文件讀取,都是基於C++。

VS 版本

在這個版本中主要是對於winows的API的調用,獲取指定文件的相關信息,主要是一個獲取文件信息的結構體

struct _finddata32_t {
        unsigned    attrib;         //文件屬性
        __time32_t  time_create;    /* -1 for FAT file systems */
        __time32_t  time_access;    /* -1 for FAT file systems */
        __time32_t  time_write;     //文件寫入時間
        _fsize_t    size;
        char        name[260];      //文件名稱
};

對於結構體中的第一個變量attrib,是用於存儲文件的相關屬性的變量,具體屬性如下:

  • _A_ARCH(存檔)
  • _A_HIDDEN(隱藏)
  • _A_NORMAL(正常)
  • _A_RDONLY(只讀)
  • _A_SUBDIR(文件夾)
  • _A_SYSTEM(系統)

其中_A_SUBDIR屬性需要用於判斷指定的路徑是“文件夾還是文即需要需要用於判斷是否存在子目錄。

具體實現代碼:Windows版本

//IDE--Visual Studio 2013
//Author--ZERO.
//In debug x64
//Time 2016/07/29
bool getFilesAll(string path, vector<string>& files)
{
    //文件句柄
    //long   hFile = 0;
    intptr_t hFile = 0;
    //文件信息
    struct _finddata_t fileinfo;
    string p;
    if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
    {
        do
        {
            //父目錄
            if ((fileinfo.attrib &  _A_SUBDIR))
            {
                if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                {
                    getFilesAll(p.assign(path).append("\\").append(fileinfo.name), files);
                }
            }
            //子目錄
            else
            {
                files.push_back(p.assign(path).append("\\").append(fileinfo.name));
            }
        } while (_findnext(hFile, &fileinfo) == 0);
        _findclose(hFile);
        return 1;
    }
    else
    {
        return 0;
    }
}

在前面使用調試過程中,當變量使用long 去定義文件句柄時會遇到以下錯誤錯誤
而且調試了很久,也不知道問題出錯在那裏。在執行
while (_findnext(hFile, &fileinfo) == 0);
來慢慢去調試,定位到源文件,看源代碼,最終把long的定義改成了intptr_t ,其定義爲:
_Check_return_ _CRTIMP int __cdecl _findnext64i32(_In_ intptr_t _FindHandle, _Out_ struct _finddata64i32_t * _FindData);
這樣問題就不存在了!!神奇。。。。

調用代碼

int main()
{
    vector<string> files;
    string path="D:'\\Data";
    if (!getFilesAll(DirPath, files))
    {
        cout << "No path here" << endl;
    }
    for (int j = 0; j<files.size(); j++)
    {
        cout << "0" << files[j].data() << endl;
    }
}

Linux 版本

主要是一開始上面的版本行不通就想換一個版本,然後就找到了Unix下的版本,由於項目開發的環境一直是Visual Studio 所以想移植,自己移植難度太大,後來github 上有人移植了。
github 鏈接
https://github.com/tronkko/dirent

我在這裏直接貼代碼了


#include <iostream>
#include <vector>
#include <string>
#include <dirent.h>
using namespace std;

bool getAllFiles( string path,vector<string>& files)
{
    struct dirent *ptr;
    struct dirent *ptrChild;
    string childPath;
    string p;
    DIR *dir;
    DIR *childDir;
    dir=opendir(path.c_str());
    if((ptr=readdir(dir))==NULL)
        return -1;
    while((ptr=readdir(dir))!=NULL)
    {
        if(ptr->d_name[0]=='.')
            continue;
        files.push_back(childPath.assign(path).append("\\").append(ptr->d_name) );
        if((ptrChild=readdir(childDir=opendir(childPath.c_str())))!=NULL)
            getAllFiles(childPath,files);
    }
    closedir(childDir);
    closedir(dir);
}
int main(int argc, char * argv[])
{
    string PATH = "F:\\Data";
    vector<string> files;
    getAllFiles(PATH,files);
    for (int i = 0; i < files.size(); ++i)
    {
        cout << files[i].data() << endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章