当前位置:   article > 正文

文件操作--遍历文件并过滤_过滤目录遍历

过滤目录遍历

1 介绍

查找某个文件夹下文件列表并做过滤是常见需求,如果要求linux+win32都支持,直接使用Qt接口很容易实现,如果直接C++库函数,稍微麻烦些。
注:c++17的STL里包含了创建文件夹的库:std::filesystem::create_directory可以直接跨平台调用,如果工程支持c++17,直接直接调用。

2 sscanf

2.1 介绍

sscanf读取格式化的字符串中的数据。
swscanf 是 sscanf 的宽字符版本;swscanf 的参数是宽字符串。 swscanf不处理 Unicode 全角十六进制或"兼容性区"字符。 除此以外,swscanf 和 sscanf 的行为完全相同。

// sscanf() 会从 str 里读进数据,依照 format 的格式将数据写入到 ... 里,注意这里的 ... 需要使用地址符号
// 转换格式参考 scanf() 即可
int sscanf(const char *str, const char *format, ...);
str -- 这是C字符串,是函数检索数据的源。
format -- 这是C字符串,包含了以下各项中的一个或多个:空格字符、非空格字符和format说明符。
附加参数 -- 这个函数接受一系列的指针作为附加参数,每一个指针都指向一个对象,对象类型由format字符串中相应的 % 标签指定,参数与 % 标签的顺序相同。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

sscanf与scanf类似,都是用于输入的,scanf以stdin为输入源,sscanf以固定字符串为输入源。

2.2 正则

% 代表选择,后跟相应条件
%* 代表过滤(即连续匹配满足条件的字符,并丢弃)
%及%* 后面紧跟的数字代表匹配的字符个数
%5[^)]代表匹配5个非)的字符,[]内是筛选的条件,^表示否定,如%[a-z]表示接收小写字母,%[A-Z0-9] 表示接收大写字母及数字
要匹配中间的字符时,应先将前面的字符用%*过滤掉
  • 1
  • 2
  • 3
  • 4
  • 5

2.3 示例

string与sscanf一起用需要注意:

#include <stdio.h>
#include <iostream>
#include <string.h>

int main()
{
    std::string str = "00-ucom-2023-05-31.log";
    std::cout << "str: " << str << std::endl;
    char tmp[10] = {0};
    int pos = 0;
    int posDel = 0;
    posDel = str.size();
    str.erase(posDel - 4, posDel - 1); 
    std::cout << "posDel = " << posDel << "; str = " << str << std::endl;
    while (sscanf(str.c_str() + pos, "%[^-]", tmp) != EOF)
    {   
        puts(tmp);
        pos += strlen(tmp) + 1;
    }   
    std::string str2 = str;
    std::cout << "str2: " << str2 << std::endl;
    pos  = 0;
    while (sscanf(str2.c_str() + pos, "%[^-]", tmp) != EOF)
    {   
        puts(tmp);
        pos += strlen(tmp) + 1;
    }   
}
结果
str: 00-ucom-2023-05-31.log
posDel = 22; str = 00-ucom-2023-05-31
00
ucom
2023
05
31
log
str2: 00-ucom-2023-05-31
00
ucom
2023
05
31

如上说明,string erase,实际还在,sscanf能访问到
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

分割字符串

#include<stdio.h>
#include<string.h>
int main()
{
	const char *buf = "a;ab;cde;xxxxxxxxxxxx;hello;world;13333;";
	char a[1024];
	int pos=0;
	while(sscanf(buf+pos,"%[^;]",a) !=EOF)
	{
		printf("%s\n",a);
		pos +=strlen(a)+1;
	}
	return 0;
}

a
ab
cde
xxxxxxxxxxxx
hello
world
13333
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

from 字符串处理函数:sscanf 的用法

// 1、取需要的字符串
int year,month,day;
sscanf("2022.09.21","%d.%d.%d",&year,&month,&day);// 提取年、月、日
printf("%d %d %d\n",year,month,day);

#2022 9 21

//2、 %ns 提取长度为 n 的字符串
char str1[10];
sscanf("20220901000","%8s",str1);// 提取长度为 8 的字符串
printf("%s\n",str1);

#20220901

// 3、将数字表示的字符串转换为整型变量
int num;
sscanf("123456","%d",&num);
printf("%d\n",num);

#123456

// 4、取到指定字符为止的字符串
char str2[10];
sscanf("test 01","%[^ ]",str2);// 取遇到空格为止的字符串
puts(str2);
char str3[10];
sscanf("test/01","%[^/]",str3);// 取遇到'/'为止的字符串
puts(str3);

#test
#test

// 5、取仅包含指定字符集的字符串
char str4[20];
sscanf("123456testSIX","%[1-9a-z]",str4);// 只取数字和小写字母
puts(str4);

#123456test

// 6、跳过不想要的数据
char str5[20];
// %s 读取时是以空格和换行作为结束标志的!
sscanf("test TEST","%*s%s",str5);// 使用 %*s 来跳过前一个字符串
puts(str5);

#TEST

// 给定一个字符串test/unique_11@qq.com,获取 / 和 @ 之间的字符串
char str6[20];
sscanf("test/unique_11@qq.com","%*[^/]/%[^@]",str6);// 先把 test/ 过滤掉,再将非'@'的一串内容送到 str6 中
puts(str6);

#unique_11

char buf[30];
sscanf("123456abcdedfBCDEF","%[1-9A-Z]",buf);// 遇到不是1-9或者A-Z的字符时,即遇到小写字母时,就已经结束
printf("%s\n",buf);

#123456
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

3 文件操作

3.1 删除文件

Windows、Linux上的形式、用法都一样
形式:remove(const char *_FileName);
头文件:stdio.h(Windows和Linux)、io.h(仅Windows)
参数:_FileName=需要删除的文件路径和文件名
说明:该函数只能删除文件,不能删除文件夹,删除成功返回0,失败返回-1.

3.2 遍历文件夹中的文件

Windows通过正则化匹配

函数:_findfirst(const char _FileName, _finddata_t _FindData),_findnext(intptr_t handle, _finddata_t* _FindData),_findclose(intptr_t handle)
结构体:_finddata_t。
头文件:io.h

string findPath = "E:/study/math/*";    //*号为正则化语法,表示附加任意字符的可匹配
struct _finddata_t fb;      //查找相同属性文件的存储结构体
intptr_t handle;            //正则化索引的句柄,用long类型会报错
handle = _findfirst(findPath.c_str(), &fb);    //匹配的第一个文件
if (handle != -1L)
{
    std::string pathTemp;
	do//循环找到的文件 
	{
	    //系统有个系统文件,名为“..”和“.”,对它不做处理  
		if (strcmp(fb.name, "..")!=0 && strcmp(fb.name, ".")!=0)//对系统隐藏文件的处理标记
		{
			// do something
		}
	} while (0 == _findnext(handle, &fb));//判断放前面会失去第一个搜索的结果
	//关闭文件夹,只有关闭了才能删除。找这个函数找了很久,标准c中用的是closedir  
	//经验介绍:一般产生Handle的函数执行后,都要进行关闭的动作。  
	_findclose(handle);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

Linux

函数:opendir(const char _FileName),readdir(DIR dir),closedir(DIR* dir)
结构体:DIR、dirent
头文件:dirent.h

string strPath = "E:/study/math/"
DIR *d = opendir(strPath.c_str());//打开这个目录
if (d != NULL)
{ 
	struct dirent *dt = NULL;
	while (dt = readdir(d))//逐个读取目录中的文件到dt
	{
		//系统有个系统文件,名为“..”和“.”,对它不做处理
		if (strcmp(dt->d_name, "..")!=0 && strcmp(dt->d_name, ".")!=0)
		{
			//do something
		}
	}
	closedir(d);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

参考

1、
2、c/c++跨平台实现新建删除文件夹(文件)及输出文件夹内所有文件名
3、输入输出与格式化字符串(C/C++)
4、百科–sscanf
5、sscanf正则表达式用法简介
6、sscanf函数与正则表达式
7、字符串处理函数:sscanf 的用法
8、C++读取文件夹中所有的文件或者是特定后缀的文件

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/617635
推荐阅读
相关标签
  

闽ICP备14008679号