文件路径的保存且进行增删改查操作--利用树进行实现,是将每个文件或文件夹保存到一个节点,然后用树形结构结构进行存储,但是存在一些问题。

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.存储文件的树且进行操作的实现

在这里我进行路径的查找时使用的时win的API,我觉得这个查找出来的更加准确。

  • 定义存储的路径的节点的结构
#pragma
#include<iostream>
#include<string>
#include<windows.h>
using namespace std;

#define MAX_FILEPATH 10000
struct BNode //构建的节点
	string file_name;
	int num;
	BNode* sub[MAX_FILEPATH];
	BNode(string path) :
		num(0),
		file_name(path) 
		for (int i = 0; i < MAX_FILEPATH; i++)
			sub[i] = NULL;
	
;
  • 创建初始的树(这个树是由初始遍历得到的路径构建的)
#include "bt_path.h"

BNode* creat_tree(string path, int* count) 
	string path_i = path + "\\\\*.*";
	WIN32_FIND_DATA pNextInfo;//保存文件信息
	HANDLE hFile = 0;
	hFile = FindFirstFile(path_i.c_str(), &pNextInfo);
    BNode* root = NULL;
    root = new BNode(path.substr(path.rfind("/") + 1));
    if (hFile)
    
        do
        
            if (pNextInfo.cFileName[0] == '.' || pNextInfo.cFileName[0] == '..')//过滤.和..
                continue;
            else 
                //dwFileAttributes值是可以一位或多位的,不好直接使用"=="来判断
                if (pNextInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)//判断是否为文件夹
                
                    //将文件夹追加到目录,成为下一级要搜索目录
                    path_i = path + "\\\\" + pNextInfo.cFileName;
                    root->sub[root->num++] = creat_tree(path_i, count);//递归
                
                else 
                    //此时为叶子节点,创建并进行输出
                    (*count)++;
                    root->sub[root->num++] = new BNode(pNextInfo.cFileName);
                    cout << path << "\\\\" << pNextInfo.cFileName << endl;
                
            
            
         while (FindNextFile(hFile, &pNextInfo));//遍历文件
    
    FindClose(hFile);
    return 0;
  • 路径的增加
    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.遇到的问题

  读取访问权限发生冲突:一般情况下两种情况会发生这样的问题。

  • 数组访问越界一般是读取位置超过此时数组的长度,当遇到读取访问冲突的提示时,如果异常发生在数组中数据的时候,可优先考虑这种情况发生。
  • 空指针异常:主要发生在通过一个指针去读取数据时。一般原因是没有初始化指针时使其成为一个空指针,指向一个不确定的值,随后进行操作。

**在指针未初始化时还会出现其他错误提示:

  1. 读取访问权限异常
  2. 0XCCCCCCCC
  3. 0XCDCDCDCD

在这里遇到的问题还没解决:在对C盘进行遍历的时候(统计了一下,大概文件与文件夹大概20多万个,遍历一半的话是没有问题的)发生了new抛出异常bad_alloc,原因是内存分配不足,有哪个大佬可以帮我看着改一下啊,蟹蟹了。

这里的问题比较多,当遍历一个文件夹下面文件多于100后会出现内存不够的现象,到现在还没有解决,如果有大佬知道为什么,麻烦您帮我这个菜鸡指出。

在这里顺便指路我的最终实现的方法,将遍历得到的文件路径存到map中,将其文件路径设置为key,MD5值为value。https://blog.csdn.net/qq_43287694/article/details/123873713

以上是关于文件路径的保存且进行增删改查操作--利用树进行实现,是将每个文件或文件夹保存到一个节点,然后用树形结构结构进行存储,但是存在一些问题。的主要内容,如果未能解决你的问题,请参考以下文章

文件路径的保存且进行增删改查操作

关于vue的增删改查操作

利用sed命令行进行增删改查

c语言 通讯录系统 增删改查 排序 动态内存开辟及文件保存与读取

c语言 通讯录系统 增删改查 排序 动态内存开辟及文件保存与读取

LSM树理解