文件路径的保存且进行增删改查操作
Posted 水澹澹兮生烟.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件路径的保存且进行增删改查操作相关的知识,希望对你有一定的参考价值。
1.要在这里掌握的一些知识
- _finddata_t 结构体是用来存储结文件结构信息的结构体
struct _finddata_t unsigned attrib;//文件属性的存储位置,他存储一个unsigned单元,用于表示文件的属性 time_t time_creat; time_t time_write; time_t time_access; _fsize_t size; char name[_MAX_FNAME]; ; //常使用的三个函数 long _findfirst(char *filespec, struct _finddata_t *fileinfo); /************************************************************ 返回值:如果查找成功的话,将返回一个long型的唯一的查找用的句柄。这个句柄将会在_findnext函数中被使用。失败返回-1. 参数: filespec:标明文件的字符串,可支持通配符。比如:*.c,则表示当前文件夹下的所有后缀为C的文件。 fileinfo :这里就是用来存放文件信息的结构体的指针。这个结构体必须在调用此函数前声明,不过不用初始化,只要分配了内存空间就可以了。函数成功后,函数会把找到的文件的信息放入这个结构体所分配的内存空间中。 ************************************************************/ int _findnext(long handle, struct _finddata_t *fileinfo); /************************************************************ 返回值:若成功返回0,否则返回-1。 参数: handle:即由_findfirst函数返回回来的句柄。 fileinfo:文件信息结构体的指针。找到文件后,函数将该文件信息放入此结构体中。 ************************************************************/ int _findclose(long handle); /************************************************************ 返回值:若成功返回0,否则返回-1。 参数: handle:即由_findfirst函数返回回来的句柄。 ************************************************************/
attrib:文件属性的存储位置,他存储一个unsigned单元,用于表示文件的属性
time_creat:用来记录文件的创建时间
time_write:记录文件最后一次修改时间
time_access:记录文件最后一次访问时间
size:文件的大小
name[_MAX_FNAME]:文件的文件名
2.存储文件的树且进行操作的实现
- 定义存储的路径的树的结构
typedef struct BNode BNode* sub[NUM + 1]; int numb; string str = ""; BNode;
- 创建一个节点
BNode* getnode(string str) BNode* root = new BNode[sizeof(BNode)]; if (root == NULL) assert(0); for(int i = 0; i< NUM;i++) root->sub[i] = NULL; root->numb = 0; root->str = str; return root;
- 创建初始的树(这个树是由初始遍历得到的路径构建的)
//根据文件进行新建 BNode* create_file(string path, int num) struct _finddata_t filei; string cur_path = path + "/*.*"; int handle = _findfirst(cur_path.c_str(), &filei); BNode* root = NULL;//定义根节点 root = getnode(path.substr(path.rfind("/") + 1)); if (handle == -1)//返回-1则查找失败 cout << "创建失败,因为此时只有根目录" << endl; return NULL; do if (filei.attrib == _A_SUBDIR) //判断是否是文件夹 //此时需要排除两种情况,当前目录,上级目录与此时的文件名称是否相同 if ((strcmp(filei.name, "..") != 0) && (strcmp(filei.name, ".") != 0)) //在这里查询,相当于找到了要存到B_tree的路径的目录的非叶子节点 // 因此我们先进行节点的创建与保存 //如果是文件夹,且进行递归的话,此时要对num进行清零 root->sub[root->numb++] = create_file(path + '/' + filei.name, root->numb); else if ((strcmp(filei.name, "..") == 0) || (strcmp(filei.name, ".") == 0)) continue; else root->sub[root->numb] = getnode(filei.name); root->numb++; else //此时遍历到了叶子节点,那么将叶子节点的值存入当中 root->sub[root->numb] = getnode(filei.name); root->numb++; while (!(_findnext(handle, &filei)));//判断此曾是否遍历完成 return root;
- 路径的增加
void add_file(BNode** root,string path, string add_path) //path是用来与取add_path中的每个文件名称的 //在增加路径的过程中,有可能会增加多个节点 BNode* cur = *(root); path = add_path.substr(0, add_path.find("/"));//从0号位置截到第一个"/"位置 add_path.erase(0, add_path.find("/")+1);//从0号位置向后删除add_path.find("/")个位置 if (cur == NULL) //当没有根目录的时候 cur = getnode(path);//创建根节点 return; else //当有根目录时,且此时根目录相同 path = add_path.substr(0, add_path.find("/"));//从0号位置截到第一个"/"位置 add_path.erase(0, add_path.find("/") + 1);//从0号位置向后删除add_path.find("/")个位置 for (int i = 0; i < cur->numb; i++) if (!strcmp(path.c_str(), (cur->sub[i])->str.c_str())) path = add_path.substr(0, add_path.find("/"));//从0号位置截到第一个"/"位置 add_path.erase(0, add_path.find("/") + 1);//从0号位置向后删除add_path.find("/")个位置 //此时,如果相同,那么继续向下进行查找 cur = cur->sub[i]; else if (cur->numb == i + 1) //此时,说明将cur的子目录遍历完且没有相同的目录,那么此时直接跳出循环 break; while (path != "") BNode* next_node = cur;//在定义一个节点,用来时节点可以向前 //当没有将所有文件插入完,继续插入节点 cur->sub[cur->numb] = getnode(path); cur->numb++; cur = cur->sub[cur->numb]; path = add_path.substr(0, add_path.find("/"));//从0号位置截到第一个"/"位置 add_path.erase(0, add_path.find("/"));//从0号位置向后删除add_path.find("/")个位置 return ;
- 路径的删除
//删除节点,遍历查询,直接删除 void del_file(BNode** root, int* num, string path, string del_path) BNode* cur = *root; if (cur == NULL) return; else //此时遍历查询,并进行比较 path = path + cur->str + "/"; //没有查找到,那么继续向下递归查询 if (strcmp(path.c_str(), del_path.c_str()) == 0) (*num)--; //当查询到有路径是相同时,则删除掉此路径下的所有文件,将这个节点下的所有数据都删除,置空 (*root)->numb = 0; *root = NULL; cout << "此时删除此路径下的所有文件成功" << endl; return; for (int i = 0; i < cur->numb; i++) del_file(&(cur->sub[i]), &(cur->numb), path, del_path); return;
- 路径的遍历查询
void find_path(BNode* root,string path) //递归遍历输出 if (root) //如果root->不为空,那么进行遍历 path = path + root->str + "/"; cout << path << endl; for (int i = 0; i < root->numb; i++) find_path(root->sub[i],path);
- 最后实现的截图
3.遇到的问题
读取访问权限发生冲突:一般情况下两种情况会发生这样的问题。
- 数组访问越界一般是读取位置超过此时数组的长度,当遇到读取访问冲突的提示时,如果异常发生在数组中数据的时候,可优先考虑这种情况发生。
- 空指针异常:主要发生在通过一个指针去读取数据时。一般原因是没有初始化指针时使其成为一个空指针,指向一个不确定的值,随后进行操作。
**在指针未初始化时还会出现其他错误提示:
- 读取访问权限异常
- 0XCCCCCCCC
- 0XCDCDCDCD
在这里遇到的问题是因为这里new无法完成内存请求,此时抛出bad_alloc来表示分配异常。
前几天遇到的一个问题,然后自己慢慢整出来的,而且代码上感觉有好多繁琐的地方,如果有时间会优化一下,如果有什么逻辑上的错误,还请多多指教。
以上是关于文件路径的保存且进行增删改查操作的主要内容,如果未能解决你的问题,请参考以下文章
文件路径的保存且进行增删改查操作--利用树进行实现,是将每个文件或文件夹保存到一个节点,然后用树形结构结构进行存储,但是存在一些问题。