基于linux的I/O编程(详细版)

   一、文件

在 Linux 中,有一句经典的话叫做:一切皆文件。这句话是站在内核的角度说的,因为 在内核中所有的设备 (除了网络接口) 都一律使用 Linux 独有的虚拟文件系统 (VFS) 来管 理。这样做的最终目的,是将各种不同的设备用“文件”这个概念加以封装和屏蔽,简化应 用层编程的难度。文件,是 Linux 系统最重要的两个抽象概念之一 (另一个是进程) 。

1、文件分类 

在 Linux 中,文件总共被分成了 7 种,他们分别是:

1,普通文件 (regular) :存在于外部存储器中,用于存储普通数据。

2, 目录文件 (directory) :用于存放目录项,是文件系统管理的重要文件类型。 3,管道文件 (pipe) :一种用于进程间通信的特殊文件,也称为命名管道 FIFO。 4,套接字文件 (socket) :一种用于网络间通信的特殊文件。

5,链接文件 (link) :用于间接访问另外一个目标文件,相当于 Windows 快捷方式。 6,字符设备文件 (character) :字符设备在应用层的访问接口。

7,块设备文件 (block) :块设备在应用层的访问接口。

注意到,每个文件信息的最左边一栏,是各种文件类型的缩写,从上到下依 次是:

b (block) 块设备文件

c (character) 字符设备文件

d (directory) 目录文件

l (link) 链接文件 (软链接)

p (pipe) 管道文件 (命名管道)

- (regular) 普通文件

s (socket) 套接字文件 (Unix 域/本地域套接字)

files_struct 结构体是 Linux 内核中表示进程打开文件的管理结构。它的原型定义可以在 Linux 内核的头文件 include/linux/fs.h 中找到。下面是 files_struct 结构体的简化原型定义:

struct files_struct {
    // 文件描述符表指针
    struct fdtable *fdt;
    // 当前进程可以打开文件的最大数量
    unsigned int max_fds;
    // 已经打开文件的数量
    unsigned long close_on_exec_init[BITS_TO_LONGS(__FD_SETSIZE)];
    // .... 其他成员和字段
};

注意,上述定义只是简化的示意,真实的 files_struct 结构体可能包含更多的成员变量和字段。在 Linux 内核源码中详细查看 include/linux/fs.h 文件可以了解完整的 files_struct 结构体定义。

 2、文件操作

对一个文件的操作有两种不同的方式,既可以使用由操作系统直接提供的编程接口  (API),即系统调用,也可以使用由标准 C 库提供的标准 IO 函数,他们的关系如图 所示。

 在 Linux 操作系统中,应用程序的一切行为都依赖于这个操作系统,但是操作系统的内 部函数应用层的程序是不能直接访问的,因此操作系统 OS 提供了大约四五百个接口函数, 叫做“系统调用接口”,好让应用程序通过他们使用内核提供的各种服务,上图中用红色标 注的那一层,就是这所谓的系统调用接口,这几百个函数是非常精炼的 (Windows 系统的 接口函数有数千个) ,他们以功能的简洁单一为美,以健壮稳定为美,但考虑到用户可能需 要用到更加丰富的功能,因此就开发了很多库,其中最重要的也是应用程序必备的库就是标 准 C 库,库里面的很多函数实际上都是对系统调用函数的进一步封装而已,用个比喻来讲 就是:OS 的系统调用接口类似于菜市场,只提供最原始的肉菜,而库的函数接口相当于饭 馆,对肉菜进行了加工,提供风味各异品种丰富的更方便食用的佳肴。

2.1、系统io 

 我们使用以下系统 IO 函数来打开一个文件:

                                                

功能

打开一个指定的文件并获得文件描述符,或者创建一个新文件

头文件

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

原型

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

参数

pathname:即将要打开的文件

flags

O_RDONLY:只读方式打开文件

这三个参数互斥

O_WRONLY:只写方式打开文件

O_RDWR:读写方式打开文件

O_CREAT:如果文件不存在,则创建该文件。

O_EXCL:如果使用 O_CREAT 选项且文件存在,则返回错误消息。

O_NOCTTY:如果文件为终端,那么终端不可以作为调用 open()系统调 用的那个进程的控制终端。

O_TRUNC:如文件已经存在,则删除文件中原有数据。

O_APPEND:以追加方式打开文件。

mode

如果文件被新建,指定其权限为 mode  (八进制表示法)

返回值

成功

大于等于 0 的整数 (即文件描述符)

失败

- 1

备注

无 

使用系统调用 open( )需要注意的问题有:

1,flags 的各种取值可以用位或的方式叠加起来,比如创建文件的时候需要满足这样的 选项:读写方式打开,不存在要新建,如果存在了则清空他。那么此时指定的 flags 的取值 应该是:O_RDWR | O_CREAT | O_TRUNC。

2,mode 是八进制权限,比如 0644,或者 0755 等。

3,它可以用来打开普通文件、块设备文件、字符设备文件、链接文件和管道文件,但 只能用来创建普通文件,每一种特殊文件的创建都有其特定的其他函数。

4,其返回值就是一个代表这个文件的描述符,是一个非负整数。这个整数将作为以后任何系统 IO 函数对其操作的句柄,或称入口。

以下的系统 IO 函数用来关闭一个文件:

功能

关闭文件并释放相应资源

头文件

#include <unistd.h>

原型

int close(int fd);

参数

fd:即将要关闭的文件的描述符

返回值

成功

0

失败

- 1

备注

重复关闭一个已经关闭了的文件或者尚未打开的文件是安全的。

函数 close( )的接口规范

系统调用 close( )相对来讲简单得多,只需要提供已打开的文件描述即可。一般来讲, 当我们使用完一个文件之后,需要及时对其进行关闭,以防止内核为继续维护它而付出不必 要的代价。如下一个完整的对文件操作的过程: 

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main()
{       //函数原型open(const char *pathname, int flags);
	int fd1 = open("./1.txt", O_RDWR);  //文件是否打开成功,返回大于等于零的整数
	//创建失败 返回-1
	if(-1 == fd1)//if(-fd = -1)  判断是否创建成功
	{
		perror("open 1.txt failed");//打印标准出错
		return -1;
	}
	//int open(const char *pathname, int flags, mode_t mode);
	//没有该文件时创建一个文件 文件路径 
	int fd2 = open("./666.txt", O_RDWR | O_CREAT , 0777);
	if(-1 == fd2)//if(-fd = -1)
	{
		perror("creat 2.txt failed");//打印标准出错
		return -1;
	}
	
	printf("fd1 = %d, fd2 = %d\n",fd1,fd2);  //输出返回值
	
	//关闭文件
	close(fd1);
	close(fd2);
	
	return 0;
}

输出结果如图所示:

 

 根据常规的理解来说,fd1和fd2应该分别是1和2吗?

       这是因为 0、1 和 2 三 个描述符在程序一开始运行时就已经被默认打开了,他们分别代表了标准输入、标准输出和 标 准 出 错 ,事 实 上 ,在代码 中 我 们 经 常 使 用 STDIN_FILENO 、 STDOUT_FILENO 和 STDERR_FILENO 来替代 0、1 和 2。

上面的示意图表示,每一个被打开的文件 (键盘、显示器都是文件) 都会有一个非负的 描述符来对应他们,一个文件还可以被重复打开多次,每打开一次也都会有一个描述符对应, 并且可以有不同的模式。

2.2、文件的读写

 接下来是文件的读写接口:

功能

从指定文件中读取数据

头文件

#include <unistd.h>

原型

ssize_t read(int fd, void *buf, size_t count);

参数

fd:从文件fd 中读数据

buf:指向存放读到的数据的缓冲区

count:想要从文件 fd 中读取的字节数

返回值

成功

实际读到的字节数

失败

- 1

备注

 实际读到的字节数小于等于 count

            

功能

将数据写入指定的文件

头文件

#include <unistd h>

原型

ssize_t write(int fd, const void *buf, size_t count);

参数

fd:将数据写入到文件 fd 中

buf:指向即将要写入的数据 

count:要写入的字节数

返回值

成功

实际写入的字节数

失败

- 1

备注

实际写入的字节数小于等于 count

函数 read( )和 write( )的接口规范 

这两个函数都非常容易理解,需要特别注意的是:

1,实际的读写字节数要通过返回值来判断,参数 count 只是一个“愿望值”。

2,当实际的读写字节数小于 count 时,有以下几种情形:

A) 读操作时,文件剩余可读字节数不足count

B) 读写操作期间,进程收到异步信号。

3,读写操作同时对 f_pos 起作用。也就是说,不管是读还是写,文件的位置偏移量 (即 内核中的 f_pos) 都会上实际读写的字节数,不断地往后偏移。

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

int main(int argc, char **argv)//参数列表,argc代表个数,argv[]代表传进来的字符串
{

	if(argc != 2)
	{
		printf("请传一个文件的路径\n");
		return -1;
	}

	int fd1 = open(argv[1], O_RDWR);  //打开文件 
	if(-1 == fd1)   //  if(-fd = -1)  将变量写在前面的好处防止将判断语句写成赋值语句
	{
		perror("open srv failed");//打印标准出错
		return -1;
	}



	char buf[128];  //定义一个buf存放128 字节


	while(1)
	{
		memset(buf,0,sizeof(buf));//内存重置

	         	//bzreo(buf, 128);

		int n = read(fd1,buf,sizeof(buf)-1);

		printf("%s",buf);  //将buf里面的内容进行输出

		if(n == 0)  //当buf读取到的字节数为零时,退出循环
		{
			break;
		}
	}

	//printf("fd1 = %d\n",fd1);

	//关闭文件
	close(fd1);

	return 0;
}

 打开当前目录下的1.txt文件 进入文件输入以下字符 运行程序后输出文件里面的内容。

 

 文件的写入

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(int argc, char **argv)  //主函数传参
{
	int fd1 = open(argv[1],O_RDWR); 打开主函数传入的函数名文件 打开方式为读写
	if(-1 == fd1) //判断是否打开成功  失败输出错误信息
	{
		printf("open %s failed, reason is %s\n",argv[1], strerror(errno));
	}

	int fd2 = open(argv[2],O_RDWR | O_CREAT, 0777);
	if(-1 == fd2)
	{
		printf("creat %s failed, reason is %s\n",argv[2], strerror(errno));
	}
	//printf("[0]=%s,[1]=%s,[2]=%s\n",argv[0],argv[1],argv[2]);
	char buf[128];  //定义一个buf 128字节

	while(1)
	{
		memset(buf,0,sizeof(buf));  //清空buf

		int n = read(fd1,buf,sizeof(buf)-1);  //buf最后一个字节为\n不添加这个-1 输出乱码

		write(fd2,buf,strlen(buf));

		if(n == 0)
		{
			break;
		}
	}

	close(fd1);
	close(fd2);

	return 0;
}

输出内容如下  :

该代码实现shell命令的文件内容复制

2.3标准 IO

系统 IO 的最大特点一个是更具通用性,不管是普通文件、管道文件、设备节点文件、 套接字文件等等都可以使用,另一个是他的简约性,对文件内数据的读写在任何情况下都是 不带任何格式的,而且数据的读写也都没有经过任何缓冲处理,这样做的理由是尽量精简内 核 API,而更加丰富的功能应该交给第三方库去进一步完善。

标准 C 库是最常用的第三方库,而标准 IO 就是标准 C 库中的一部分接口,这一部分接 口实际上是系统 IO 的封装,他提供了更加丰富的读写方式,比如可以按格式读写、按 ASCII 码字符读写、按二进制读写、按行读写、按数据块读写等等,还可以提供数据读写缓冲功能, 极大提高程序读写效率。

在 2.1 中,所有的系统 IO 函数都是围绕所谓的“文件描述符”进行的,这个文件描 述符由函数 open( )获取,而在这一节中,所有的标准 IO 都是围绕所谓的“文件指针”进 行的,这个文件指针则是由 fopen( )获取的,他是第一个需要掌握的标准 IO 函数:

功能

获取指定文件的文件指针

头文件

#include <stdio.h>

原型

FILE *fopen(const char *path, const char *mode);

参数

path:即将要打开的文件

mode

“r” :  以只读方式打开文件,要求文件必须存在。

“r+” :  以读写方式打开文件,要求文件必须存在。

“w” :  以只写方式打开文件,文件如果不存在将会创建新文件,如果存 在将会将其内容清空。

“w+” :  以读写方式打开文件,文件如果不存在将会创建新文件,如果存 在将会将其内容清空。

“a” :  以只写方式打开文件,文件如果不存在将会创建新文件,且文件位 置偏移量被自动定位到文件末尾 (即以追加方式写数据) 。

“a+” :  以读写方式打开文件,文件如果不存在将会创建新文件,且文件 位置偏移量被自动定位到文件末尾 (即以追加方式写数据) 。

返回值

成功

文件指针

失败

NULL

备注

上表为函数 fopen( )的接口规范

fopen( )一起配套使用的是 fclose( )

关闭指定的文件并释放其资源

文件

#include <stdio.h>

int fclose(FILE *fp);

参数

fp:即将要关闭的文件

回值

成功

0

EOF

函数 fclose( )的接口规范

函数用于释放由 fopen( )申请的系统资源,包括释放标准 IO 缓冲区内存,因此 fclose( )不能对一个文件重复关闭。

每次读写若干数据块的标准 IO 函数接口:fread、fwrite

从指定文件读取若干个数据块

文件

#include <sys/ioctl.h>

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数

ptr 自定义缓冲区指针

size:数据块大小

nmemb:数据块个数

stream:即将被读取数据的文件指针

回值

成功

读取的数据块个数,等于 nmemb

取的数据块个数,小于 nmemb 或等于 0

当返回小与nmemb 时,文件 stream 可能已达末尾,或者遇到错误

将若干块数据写入指定的文件

文件

#include <sys/ioctl.h>

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

参数

ptr 自定义缓冲区指针

size:数据块大小

nmemb:数据块个数

stream:即将被写入数据的文件指针

回值

成功

入的数据块个数,等于 sinmembze

写入数据块个数,小于 nmemb 或等于 0

每次读写若干数据块的函数接口规

这一标准 IO 函数被称为“直接 IO 函数”或者“二进制 IO 函数”,因为他们对数据 的读写严格按照规定的数据块数和数据块的大小来处理,而不会对数据格式做任何处理,而 且当数据块中出现特殊字符,比如换行符’\n’、字符串结束标记’\0’等时不会受到影响。

需要注意:

如果 fread( )返回值小于 nmemb 时,则可能已达末尾,或者遇到错误,需要借助于 feof( )/ferror( )来加以进一步判断。

举例代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	
	FILE *fp = fopen("./cli.c", "r");//fp->
	if(fp == NULL)
	{
		perror("open 1.txt failed");
		return -1;
	}
	
	printf("%d\n",fp->_fileno);
	
	
	char *ptr = calloc(5,20);//malloc(),参数个数,用malloc申请的空间,内容不会初始化,calloc会初始化申请的空间
	
	while(1)
	{
		memset(ptr,0,100);
		long start = ftell(fp);
		int nmemb = fread(ptr,20,5,fp);//读到的数据块的个数,100个字节,文件128个,5,1
		printf("%s",ptr);
		if(nmemb == 0)//退出条件
		{
			fclose(fp);
			break;
		}
		
		// if(nmemb == 5)
		// {
			// printf("%s", ptr);
		// }
		
		// if(nmemb < 5)
		// {
			// long end = ftell(fp);//不满100个字节
			// //printf("%s\n", ptr);//end - start = 整数
			// fread(ptr,end - start,1,fp);
			
			// printf("%s",ptr);
			
			// fclose(fp);
			// break;
		// }
		
	}
	
	
	//fclose(fp);
	
	return 0;
	
	
}



2.4 系统IO与标准IO的区别

可以看到,使用标准 IO 数处理文件的最大特点是,数据将会先存储在一个标准 IO 缓冲区中,而后在一定条件下才被一并 flush (冲洗,或称刷新) 至内核缓冲区,而不是像 系统 IO 那样,数据直接被flush 内核。

注意到标准 IO 函数 fopen( )实质上是系统 IO 函数 open( )的封装,他们是一一对应 的,每一次 fopen( )都会导致系统分配一个 file{ }结构体和一个 FILE{}来保存维护该文件的 读写信息,每一次的开和操作都可以不一样,是相对独立的,因此可以在多线程或者多进 程中多次打开同一个文件,再利用文件空洞技术进行多点读写。

2.4获取或设置文件当前位置偏移量。

功能

设置指定文件的当前位置偏移量

头文件

#include <sys/ioctl.h>

原型

int fseek(FILE *stream, long offset, int whence);

参数

stream:需要设置位置偏移量的文件指针

offset:新位置偏移量相对基准点的偏移

whence:基准点

SEEK_SET:文件开头处

SEEK_CUR:当前位置

SEEK_END:文件末尾处

返回值

成功

0

失败

- 1

备注

功能

获取指定文件的当前位置偏移量

头文件

#include <sys/ioctl.h>

原型

long ftell(FILE *stream);

参数

stream:需要返回当前文件位置偏移量的文件指针

返回值

成功

当前文件位置偏移量

失败

- 1

备注

功能

将指定文件的当前位置偏移量设置到文件开头处

头文件

#include <sys/ioctl.h>

原型

void rewind(FILE *stream);

参数

stream:需要设置位置偏移量的文件指针

返回值

备注

该函数的功能是将文件 strean 的位置偏移量置位到文件开头处。

调整文件位置偏移量的函数接口规范

这一组函数需要注意的几点是:

1fseek( )的用法基上跟系统 IO lseek( )是一致的。

2rewind(fp)相等于 fseek(fp, 0L, SEEK_SE);

 #include <stdio.h>
2   #include <stdlib.h>
3   #include <stdbool.h>
4   #include <unistd.h>
5   #include <string.h>
6   #include <strings.h>





7   #include <errno.h>
8
9   #include <sys/stat.h>
10   #include <sys/types.h>
11   #include <fcntl.h>
12
13   #define SIZE 100
14   #define NMEMB 5
15
16   int main(int argc, char **argv) 17  {
18         if(argc != 3) 19         {
20               printf("Usage: %s <src> <dst>\n", argv[0]);
21               exit(1);
22         }
23
24         // 分别以只读和只写模式打开源文件和目标文件
25         FILE *fp_src = fopen(argv[1], "r");
26         FILE *fp_dst = fopen(argv[2], "w"); 27
28         // 如果返回 NULL 则程序出错退出
29         if(fp_src == NULL || fp_dst == NULL) 30         {
31               perror("fopen()");
32               exit(1); 33         }
35         char buf[SIZE * NMEMB];
36         int total = 0;
37         long pos1, pos2;
38         while(1) 39         {
40               bzero(buf, SIZE * NMEMB);
41               pos1 = ftell(fp_src); // 获取当前源文件的位置偏移量
42               if(fread(buf, SIZE, NMEMB, fp_src) < NMEMB) // 发生了异常 43               {
44                      if(feof(fp_src)) //  已达文件末尾
45                      {
46                            pos2 = ftell(fp_src); // 将剩余的字节写入目标文件
47                            fwrite(buf, pos2-pos1, 1, fp_dst);
48                            total += (pos2 - pos1); 49
50                            printf("copy completed, %d bytes" 51                                   " have been copied.\n", total);





52                            break; 53                      }
54                      else if(ferror(fp_src)) // 遇到错误 55                      {
56                            perror("fread()");
57                            break;
58                      }
59               }
61               fwrite(buf, SIZE, NMEMB, fp_dst); // 将数据写入目标文件
62               total += SIZE*NMEMB; 63         }
65         // 正常关闭文件指针,释放系统资源
66         fclose(fp_src);
67         fclose(fp_dst); 68
69         return 0;
70   }

标准格式化 IO 函数。

格式化 IO 函数最常用的莫过于 printf( )scanf( )了,但从上表中可以看到,他们其 实各自都有一些功能类似的兄弟函数可用,使用这些函数需要注意以下几点:

1fprintf( )不仅可以像 printf( )一样向标准输出设备输出信息,也可以向由 stream  定的任何有相应权限的文件写入数据。

2sprintf()snprintf()都是向一块自定义缓冲区写入数据,不同的是后者第二个参数 提供了这块缓冲区的大小,避免缓冲区溢出,因此应尽量使用后者,放弃使用前者。

3 fscanf( )不仅可以像 scanf( )一样从标准输入设备读入信息,也可以从由 stream  定的任何有相应权限的文件读入数据。

4,sscanf( )从一块由 s 指定的自定义缓冲区中读入数据。

5,最重要的一条:这些函数的读写都是带格式的,这些所谓的格式由下表规定:

格式控制符

含义

范例 (以 printf( )为例)

%d

有符号十进制整型数

int a=1; printf(“%d”, a);

%u

无符号十进制整型数

int a=1; printf(“%u”, a);

%o

无符号八进制整型数

int a=1; printf(“%o”, a);

%x

无符号十六进制整型数

int a=1; printf(“%x”, a);

%c

字符

char a=100; printf(“%c”, a);

%s

字符串

char *a=”xy”; printf(“%s”, a);

%f

计数法单精度浮点数

float a=1.0; printf(“%f”, a);

%e

科学技术法单精度浮点数

float a=1.0; printf(“%e”, a);

%p

指针

int *a; printf(“%p”, a);

%.5s

取字符串的前 5 个字符

char *a=”abcdefghijk”;

printf(“%.5s”, a);

%.5f

取单精度浮点数小数点后 5 位小数

float a=1.0; printf(“%.5f”, a);

%5d

位宽至少为 5 个字符,右对齐

int a=1; printf(“%5d”, a);

%-5d

位宽至少为 5 个字符,左对齐

int a=1; printf(“%-5d”, a);

%hd

半个有符号数十进制整型数

short a=1; printf(“%hd”, a);

%hhd

半半个有符号数十进制整型数

char a=1; printf(“%hhd”, a

 

%lf / %le

精度浮点数

double a=1.0; printf(“%lf”, a);

%Lf / %Le

长双精度浮点数

long double a=1.0;

printf(“%Lf”, a);

3、目录检索 

  3. 1  基本概念

在 Linux 中的目录的概念,跟 Windows 中的文件夹的概念很容易让人混淆,很多人甚 至将他们认为是一样的东西的两种不同称呼而已,其实不是,Windows 中的文件夹类似于 一种容器,大文件夹里面放了很多文件以及子文件夹,子文件夹里面又套有别的文件夹,一 层套一层,就像俄罗斯套娃,但是不管怎么套,里面的总比外面的小,在 Windows 中子文件夹是不可能比外部文件夹还大的。

但是 Linux 中的目录并不是一种容器,而仅仅是一个文件索引表,下面这幅图是第一章 介绍ls 命令时看到的分区和目录的关系图: 

Linux 文件系统的组织

Linux 中目录就是一组由文件名和索引号组成的索引表,目录下的文件的真正内容存储 在分区中的数据域区。目录中索引表的每一项被称为“目录项”,里面至少存放了一个文 件的名字 (不含路径部分) 和索引号 (分区唯一) ,当我们访问某一个文件的时候,就是根 据其所在的目录的索引表中的名字,找到其索引号,然后在分区的 i-node 节点域中查找到 应的文件 i 节点的。

3.2  相关 API

现在来看看,对于一个目录而言,我们是怎么处理的。其实操作目录跟标准 IO 函数操 作文件类似,也是先获得“ 目录指针”,然后读取一个个的“目录项”。用到的接口函数是:

功能

打开目录以获得目录指针

头文件

#include <sys/types.h>

#include <dirent.h>

原型

DIR *opendir(const char *name);

参数

name: 目录名

返回值

成功

目录指针

失败

NULL

备注

功能

读取目录项

头文件

#include <dirent.h>

原型

struct dirent *readdir(DIR *dirp);

参数

dirp:读出目录项的目录指针

返回值

成功

目录项指针

失败

NULL

备注

表 4-22 函数 opendir( )和 readdir( )的接口规范

从目录中读到的所谓目录项,是一个这样的结构体:

struct dirent

{

ino_t d_ino; // 文件索引号

off_t d_off; //  目录项偏移量

unsigned short d_reclen; // 该目录项大小

unsigned char d_type; // 文件类型

char d_name[256]; // 文件名

};

举例如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>



int main(int argc , char **argv)
{
	DIR *dir = NULL;
	
	dir = opendir(argv[1]);
	if(NULL == dir)
	{
		perror("open argv[1] failed");
		return -1;
	}
	
	
	
	
	
	return 0;
	
}

   

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值