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;
}