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