itop-3568 开发板系统编程学习笔记(3)目录 IO

news2024/11/15 21:34:00

【北京迅为】嵌入式学习之Linux系统编程篇 https://www.bilibili.com/video/BV1zV411e7Cy/ 个人学习笔记

文章目录

  • mkdir() 函数
  • opendir() 和 closedir() 函数
  • readdir() 函数
  • 综合实验

mkdir() 函数

  • 头文件:
#include <sys/types.h>
#include <sys/stat.h>
  • 函数定义
 int mkdir(const char *pathname, mode_t mode);

pathname 为要创建的目录路径名,mode 用来指定新建文件夹的权限(与文件 IO 的 mode 参数相同),下面是文件 IO 中 mode 参数的介绍:

#define S_IRUSR 00400 /*文件所有者可读*/
#define S_IWUSR 00200 /*文件所有者可写*/
#define S_IXUSR 00100 /*文件所有者可执行*/
#define S_IRGRP 00040 /*与文件所有者同组的用户可读*/
#define S_IWGRP 00020 /*与文件所有者同组的用户可写*/
#define S_IXGRP 00010 /*与文件所有者同组的用户可执行*/
#define S_IROTH 00004 /*与文件所有者不同组的用户可读*/
#define S_IWOTH 00002 /*与文件所有者不同组的用户可写*/
#define S_IXOTH 00001 /*与文件所有者不同组的用户可可执行*/

#define S_IRWXUGO	(S_IRWXU|S_IRWXG|S_IRWXO)	/* 所有用户可读、写、执行 */
#define S_IALLUGO	(S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)/* 所有用户可读、写、执行*/
#define S_IRUGO		(S_IRUSR|S_IRGRP|S_IROTH)	/* 所有用户可读 */
#define S_IWUGO		(S_IWUSR|S_IWGRP|S_IWOTH)	/* 所有用户可写 */
#define S_IXUGO		(S_IXUSR|S_IXGRP|S_IXOTH)	/* 所有用户可执行 */

如果直接填 0644(0不能省略,0644 代表八进制数 644),表示文件所有者可读写,同组用户和其他用户只读。

上面是文件权限的介绍,如要要访问目录,需要加上可执行权限

  • 返回值:

创建成功返回 0,失败返回 -1 。

opendir() 和 closedir() 函数

opendir()

  • 头文件:
#include <sys/types.h>
#include <dirent.h>
  • 函数定义
DIR *opendir(const char *name);

name 为要打开的目录名

  • 返回值:

操作成功返回目录的指针,失败返回 NULL。

closedir()

  • 头文件:
#include <sys/types.h>
#include <dirent.h>
  • 函数定义
int closedir(DIR *dirp);

目录指针 dirp 是 opendir 返回的变量,指向要关闭的目录。

  • 返回值:

操作成功返回 0 ,失败返回 -1 。

readdir() 函数

  • 头文件:
#include <dirent.h>
  • 函数定义
struct dirent *readdir(DIR *dirp);

目录指针 dirp 是 opendir 返回的变量,指向要读取的目录。

  • 返回值:

读取目录成功,返回一个静态定义的 struct dirent 变量,如果出错或者读到目录流的末尾,返回 NULL。

struct dirent 结构体定义如下:

struct dirent {
	ino_t          d_ino;       /* inode number */
	off_t          d_off;       /* not an offset; see NOTES */
	unsigned short d_reclen;    /* length of this record */
	unsigned char  d_type;      /* type of file; not supported
	                               by all filesystem types */
	char           d_name[256]; /* filename */
           };

d_type(文件类型)和 d_name(文件名)是我们要用到的成员变量,d_type 的可取值包括:

这些宏在 dirent.h 有声明,我们无需知道它们具体的数值是多少

在这里插入图片描述

使用参考:

// 打印目录类型
void print_dir_type(unsigned char d_type)
{
	switch (d_type) 
	{
		case DT_DIR: // a directory
		printf("directory");
		break;
		case DT_REG: // a regular file
		printf("regular file");
		break;
		case DT_BLK: // a block device
		printf("block device");
		break;
		case DT_CHR: // a character device
		printf("character device");
		break;
		case DT_FIFO: // a named pipe (FIFO)
		printf("named pipe (FIFO)");
		break;
		case DT_LNK: // a symbolic link
		printf("symbolic link");
		break;
		case DT_SOCK: // a UNIX domain socket
		printf("UNIX domain socket");
		break;
		default: // DT_UNKNOWN - file type unknown
		printf("The file type is unknown");
		break;
	}
}

readdir() 每次只能读到一个文件的信息,所以如果要遍历整个目录,需要用到循环,参考代码如下:

// 调用readdir遍历目录子文件
struct dirent *dir;
while((dir = readdir(dp)) != NULL)
{
  // 打印文件名、文件类型等信息
}

综合实验

打印 A 目录下所有文件名,并拷贝 A 目录下的 a.c 到 B 目录下的 b.c

为了简化代码,这里引入两个库函数:

#include <libgen.h>
char *dirname(char *path);  //返回目录名
char *basename(char *path); //返回文件名

注意:使用 dirname(path) 后,path 字符串也会发生变化,所以实际使用时需要提前将 path 备份

在 shell 下面也有对应的命令,

在这里插入图片描述

实验代码:

仅供参考

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

char BUFF[1024];

//打印目录类型
void print_dir_type(unsigned char d_type);

//文件拷贝(上一篇笔记代码)
int my_copy(char *src, char *dest);

int main(int argc, char *argv[])
{
	int ret;
	DIR *dp;
	struct dirent *dir;
	char src_filename[20];
	char dest_filename[20];

	if(argc != 3)
	{
		printf("用法:%s <源文件> <目标文件>.\n", argv[0]);
		return -1;
	}
	
	// 获取(备份)文件名(路径),两条语句功能类似
	sprintf(src_filename, "%s", argv[1]);
	strncpy(dest_filename, argv[2], 20); 

	// 打开源文件目录,之后 argv[1] 变为目录名
	dp = opendir(dirname(argv[1]));
	if(dp == NULL)
	{
		printf("目录为空.\n");
		return -2;
	}
	printf("%s 打开成功.\n", argv[1]);

	while((dir = readdir(dp)) != NULL)
	{
		printf("文件名:%-20s", dir->d_name);
		printf("\t文件类型:");
		print_dir_type(dir->d_type);
		printf("\n");
	}

	// 关闭目录
	closedir(dp);

	// 创建目标文件的目录,之后 argv[2] 变为目录名
	ret = mkdir(dirname(argv[2]), 0755);
	if(ret < 0)
	{
		printf("%s 创建失败.\n", argv[2]);	
		return -3;
	}
	printf("%s 创建成功.\n", argv[2]);

	// 文件操作(上一篇笔记代码)
	my_copy(src_filename, dest_filename);

	return 0;
}

// 打印目录类型
void print_dir_type(unsigned char d_type)
{
	switch (d_type) 
	{
		case DT_DIR: // a directory
		printf("directory");
		break;
		case DT_REG: // a regular file
		printf("regular file");
		break;
		case DT_BLK: // a block device
		printf("block device");
		break;
		case DT_CHR: // a character device
		printf("character device");
		break;
		case DT_FIFO: // a named pipe (FIFO)
		printf("named pipe (FIFO)");
		break;
		case DT_LNK: // a symbolic link
		printf("symbolic link");
		break;
		case DT_SOCK: // a UNIX domain socket
		printf("UNIX domain socket");
		break;
		default: // DT_UNKNOWN - file type unknown
		printf("The file type is unknown");
		break;
	}
}

//文件拷贝(上一篇笔记代码)
int my_copy(char *src, char *dest)
{
	int ret = 0, sum = 0;
	int fd1, fd2;

	// 打开 src
	fd1 = open(src, O_RDONLY);
	if(fd1 < 0)
	{
		printf("%s 打开失败.\n", src);	
		return -1;
	}

	// 读取 src 文件大小
	ret = lseek(fd1, 0, SEEK_END);
	if(ret != 0)
	{
		printf("%s 大小为 %d bytes.\n", src, ret);
		lseek(fd1, 0, SEEK_SET); // 将文件指针指向开头
	}
	else
	{
		printf("%s 为空, 操作失败.\n", src);
		return -2;
	}

	// 打开(创建)dest,写入文件采用截断的方式
	fd2 = open(dest, O_CREAT|O_TRUNC|O_RDWR, 0644);
	if(fd2 < 0)
	{
		printf(" 打开失败.\n");	
		return -3;
	}

	// 将 src 内容拷贝到 dest
	while((ret = read(fd1, BUFF, 1024)) != 0)
	{
		sum += write(fd2, BUFF, ret);
	}
	printf("成功向 %s 写入 %d bytes.\n", dest, sum);

	
	// 关闭 src 和 dest
	close(fd1);
	close(fd2);
	
	return 0;
}

程序运行结果:(打印 A 目录下的所有文件,并将 A/a.c 拷贝到 B/b.c)

在这里插入图片描述


tips:

  • 文件夹已存在的情况下,再使用 mkdir 创建目录,该函数不会返回 0,所以我提前将原来的 B/ 删除,当然,我们也可以根据 mkdir 的错误号来决定下一步如何操作,而不是像上面那样不成功就直接退出程序。
  • 创建目录时,需要比普通文件多一个可执行权限,否则无法进入目录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/381881.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux代码调试-gdb

在windows调试各类代码经常依托相关便利的IDE工具&#xff0c;如Microsoft的Visual Studio,TI的Code Composer Studio,ADI的CrossCore Embedded Studio ,ADI的VisualDSP&#xff0c;Renesas的CS for CC,NXP的S32 Design Studio…这些调试&#xff0c;或借助软、硬件仿真&#x…

JPA 之 Hibernate EntityManager 使用指南

Hibernate EntityManager 专题 参考&#xff1a; JPA – EntityManager常用API详解EntityManager基本概念 基本概念及获得 EntityManager 对象 基本概念 在使用持久化工具的时候&#xff0c;一般都有一个对象来操作数据库&#xff0c;在原生的Hibernate中叫做Session&…

排序之损失函数List-wise loss(系列3)

排序系列篇&#xff1a; 排序之指标集锦(系列1)原创 排序之损失函数pair-wise loss(系列2)排序之损失函数List-wise loss(系列3) 最早的关于list-wise的文章发表在Learning to Rank: From Pairwise Approach to Listwise Approach中&#xff0c;后面陆陆续续出了各种变形&#…

SpringBoot入门 - SpringBoot HelloWorld

我们了解了SpringBoot和SpringFramework的关系之后&#xff0c;我们可以开始创建一个Hello World级别的项目了。创建 SpringBoot Web 应用为快速进行开发&#xff0c;推荐你使用IDEA这类开发工具&#xff0c;它将大大提升你学习和开发的效率。选择 Spring InitializeSpring提供…

开源的 OA 办公系统 — 勾股 OA 4.3.01 发布

勾股 OA 办公系统是一款简单实用的开源的企业办公系统。系统集成了系统设置、人事管理、行政管理、消息管理、企业公告、知识库、审批流程设置、办公审批、日常办公、财务管理、客户管理、合同管理、项目管理、任务管理等功能模块。系统简约&#xff0c;易于功能扩展&#xff0…

【vue】图标选择(elementUI和svg结合)

目标&#xff1a;在做菜单权限的时候需要选择图标&#xff0c;如果既想要用elementUI自带的图标&#xff0c;还想要自定义的图标&#xff0c;这时就需要二者结合一下如果用的是vue-admin-template&#xff0c;那svg组件和引入elementUI是不需要操作的&#xff0c;直接使用即可。…

pytest学习和使用17-Pytest如何重复执行用例?(pytest-repeat)

17-Pytest如何重复执行用例&#xff1f;&#xff08;pytest-repeat&#xff09;1 使用场景2 pytest-repeat插件2.1 环境要求2.2 插件安装3 pytest-repeat使用3.1 重复测试直到失败3.2 用例标记执行重复多次3.3 命令行参数--repeat-scope详解3.3.1 class示例3.3.2 module示例1 使…

如何在软件测试面试中脱颖而出?(附教程)天花板都这样回答

面试软件测试工程师岗位&#xff0c;是否真的如网上所说&#xff0c;需要不停刷面试题?面试题可能掌握的技巧实际是一样的&#xff0c;只是题目形式不一样&#xff0c;那么应该如何在面试中脱颖而出呢?今天我们就来聊一聊。 我录制了一整套完整的软件测试面试的话术教程&…

拿下32k成功入职阿里软件测试面试常见问题及回答技巧

1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件平台上是否可以正常的运行&#xff0c;即是通常说的软件的可移植性。 兼容的类型&#xff0c;如果细分的话&#xff0c;有平台的兼容…

测试结束参考标准

在软件消亡之前&#xff0c;如果没有测试的结束点&#xff0c;那么软件测试就永无休止&#xff0c;永远不可能结束。软件测试的结束点&#xff0c;要依据自己公司具体情况来制定&#xff0c;不能一概而论!个人认为测试结束点由以下几个条件决定&#xff1a; 1.基于“测试阶段”…

预览版Edge申请微软new Bing失败解决方案

文章目录1.首先需要配置科学上网2.下载预览版Edge浏览器卡它bug&#xff01;卡它bug&#xff01;卡它bug&#xff01;没有申请上ChatGPT的朋友们&#xff0c;试试new Bing吧&#xff0c;更新更强大&#xff0c;关于申请方式&#xff0c;网上已经有很多帖子了&#xff0c;其中一…

WebRTC 拥塞控制 | Trendline 滤波器

1.指数平滑1.1一次指数平滑法&#xff08;Single Exponential Smoothing&#xff09;指数平滑法&#xff08;Exponential Smoothing&#xff09; 是在移动平均法基础上发展起来的一种时间序列分析预测法&#xff0c;它是通过计算指数平滑值&#xff0c;配合一定的时间序列预测模…

fiddler抓包实战(1),模拟手机弱网测试,判断BUG来自客户端还是服务端

手机app中常见的测试之一就是弱网测试&#xff0c;什么是弱网测试呢?顾名思义就是模拟弱网的时候用户对于手机的一些操作和响应是否成功&#xff0c;在使用的过程中是否能够正常的使用 手机端常见弱网测试方法就是切换5G、4G、3G、2G这样 Web中就可以直接模拟打开F12然后就可…

Linux C++ 内存映射文件及其应用

Linux C 内存映射文件及其应用一. 原理二. 应用场景1. 实现多进程通信2. 实现内存持久化3.实现读写大文件三. 问答参考链接一. 原理 内存映射文件&#xff0c;是从一个文件到一块内存的映射。 内存映射文件与虚拟内存有些类似&#xff0c;通过内存映射文件可以将文件与内存中一…

【ESP32+freeRTOS学习笔记-(十)任务通知机制】

目录1、任务通知&#xff08;Task Notifications&#xff09;概念1.1 概念1.2 使用任务通知的优势1.3 无法使用任务通知的场景2、使用任务通知2.1 xTaskNotifyGive()2.2 ulTaskNotifyTake()2.3 使用任务通知代替信号量&#xff0c;方法12.4 使用任务通知代替信号量&#xff0c;…

mtd和嵌入式系统分区

一. MTD介绍 嵌入式系统的磁盘分区情况&#xff0c;一般由mtd来表示。 MTD&#xff08;Memory Technology Device)&#xff1a;内存技术设备是Linux的存储设备中的一个子系统。其设计此系统的目的是&#xff0c;对于内存类的设备&#xff0c;提供一个抽象层&#xff0c;一个接口…

【计算机三级网络技术】 第五篇 局域网技术基础及应用

文章目录一、局域网组网基础知识1.局域网的主要特征2.局域网标准3.交换式局域网4.虚拟局域网技术二、综合布线基本概念1.综合布线系统的组成2.综合布线的优点3.综合布线的设计等级4综合布线系统标准三、局域网互联设备1.中继器2.集线器3.网桥&#xff08;Bridge&#xff09;4.交…

eKuiper 1.8.0 发布:零代码实现图像/视频流的实时 AI 推理

LF Edge eKuiper 是 Golang 实现的轻量级物联网边缘分析、流式处理开源软件&#xff0c;可以运行在各类资源受限的边缘设备上。eKuiper 的主要目标是在边缘端提供一个流媒体软件框架&#xff08;类似于 Apache Flink &#xff09;。eKuiper 的规则引擎允许用户提供基于 SQL 或基…

10_创建和管理表

表操作基础1.1 一条数据存储的过程存储数据是处理数据的第一步 。只有正确地把数据存储起来&#xff0c;我们才能进行有效的处理和分析。否则&#xff0c;只能是一团乱麻&#xff0c;无从下手。那么&#xff0c;怎样才能把用户各种经营相关的、纷繁复杂的数据&#xff0c;有序、…

CIMCAI intelligent railway logistics world leading container AI

港航人工智能/集装箱人工智能领军企业CIMCAI&#xff0c;多式联运智能化铁路货运智能化方案&#xff0c;全自动化集装箱识别数字化海运铁路运输集装箱管理。CIMCAI中集飞瞳是世界应用落地最广&#xff0c;规模最大&#xff0c;最先进的的集装箱人工智能高科技企业。世界集装箱A…