IO--------->第二天,文件IO

文件IO

文件IO的特点:

  1. 文件IO是POXIC(可移植操作系统接口)定义的一组函数
  2. 不提供缓冲机制,每次读写都会引起系统调用
  3. 文件描述符,是一个非负整数,文件描述符是0开始的

标准IO默认打开3个文件   stdin           标准输入    0

                                         stdout          标准输出    1

                                         stderr          标准出错    2

     4.Linux下,标准IO基于文件IO实现

文件的打开和关闭

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

参数1:文件名(可包含路径)

参数2:打开方式

      O_RDONLY   以只读方式打开文件

      O_WRONLY   以只写方式打开文件

      O_RDWR     以读写方式打开文件

      O_CREAT     如果该文件不存在,就创建一个新的文件

                   并用第三参数为其设置权限

      O_TRUNC     如果文件存在,那么打开文件时先删除文件中原有数据

      O_EXCL       如果该文件存在,则报错

      O_APPEND    以添加方式打开文件,所以对文件的写操作都在文件的末尾进行

      O_NOCTTY   

  第三个参数:文件的权限 0777

   

返回值:成功返回文件描述符,若失败,则返回-1

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

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

#include <unistd.h>

int close(int fd);

文件掩码:

0777             0 111 111 111         0 111 111 111

              & ~    000 000 010     &    111 111 101

                     _____________________________

                                                      111 111 101------->775

文件的读写

#include <unistd.h>

参数1:文件描述符

参数2:空间的首地址

参数3:一次性读取多少个字节

返回值:成功返回具体的个数,失败则返回-1,

      返回0表示到达文件末尾或无可读取的数据

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

函数功能:将buf指向空间中count个字节写入到fd这个文件中

参数1:文件描述符

参数2:首地址

参数3:写入的字节数

返回值:成功具体写入的字节数

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

练习:模拟cp命令 (复制照片)

1------以只读方式打开文件1.png给fr     open()

2------以只写方式打开文件2.png给fw    open()

3------从fr中读取n个字节给buf         read()

4------将读到的n个字节写入到fw中去    write()

5------循环3,4,直到n==0  

6------关闭fr,fw                        close()

#include <stdio.h>
#include "io.h"
#include <string.h>

#define SIZE 20

int main(int argc, const char *argv[])
{
	//1.以只读方式打开文件
	int fr=0;
	fr=open(argv[1],O_RDONLY);
	if(0>fr)
	{
		perror("file open error");
		return -1;
	}
	
	//2.以只写方式打开文件,文件不存在则新建,文件存在则清空文件内容
	int fw=0;
	fw=open(argv[2],O_WRONLY|O_CREAT|O_APPEND,0777);
	if(0>fw)
	{
		perror("file open error");
		return -1;
	}
	
	//3.从文件读取字节
	char buf[SIZE]={'\0'};

	while(1)
	{
		memset(buf,'\0',sizeof(buf));
		int n=read(fr,buf,SIZE);
		if(0==n)
		{
			break;
		}
	//4.给文件写入字节
		write(fw,buf,sizeof(buf));
	}

	//5.关闭文件
	close(fr);
	close(fw);

	return 0;
}

文件其他相关函数

#include <sys/types.h>

#include <unistd.h>

函数功能:移动文件指针

参数1:文件描述符

参数2:偏移量

参数3:位置     SEEK_SET

                         SEEK_CUR

                         SEEK_END

off_t lseek(int fd, off_t offset, int whence);

空洞文件

1.什么是空洞文件?

“在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。”

2.空洞文件有什么用?

例如:迅雷下载文件时,在未下载完成时就已经占据了全部文件大小的空间,这时候就是空洞文件。下载的时候如果没有空洞文件,多线程下载时文件就都只能从一个地方写入,这就不是多线程了。如果有了空洞文件,可以从不同的地址写入,就完成了多线程的优势任务。

如何创建一个空洞文件

  1. 以只写的方式打开该文件
  2. 移动文件指针,移动1G
  3. 在末尾写一个字节
  4. 关闭文件
#include <stdio.h>
#include "io.h"

int main(int argc, const char *argv[])
{
	//1.以只写的方式打开该文件,文件不存在则新建,文件存在,则清空文件内容
	int fw=0;
	fw=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0777);
	if(0>fw)
	{
		perror("opne error");
		return -1;
	}

	//2.移动文件指针,移动1G
	lseek(fw,1024*1024*1024,SEEK_SET);

	//3.在文件末尾写个字节
	write(fw,"\0",1);

	//4.关闭文件
	close(fw);

	return 0;
}

目录打开和关闭

#include <sys/types.h>

#include <dirent.h>

参数1: 目录名

返回值:  成功返回DIR *,失败则返回NULL

DIR *opendir(const char *name);

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

目录的读取

 struct dirent {

               ino_t          d_ino;       /* inode number */------>索引节点号 

               off_t          d_off;       /* offset to the next dirent */--------->在目录文件中的偏移

               unsigned short d_reclen;    /* length of this record */

               unsigned char  d_type;      /* type of file; not supported

                                              by all file system types */ ------>文件类型

               char           d_name[256]; /* filename */   --->文件名

 };

#include <dirent.h>

参数1:打开的目录指针

返回值:成功struct dirent *,失败则返回NULL

struct dirent *readdir(DIR *dirp);

ls -a(查看所有以./开头的文件,表示隐藏文件)

#ifndef _DIR_H
#define _DIR_H

//引入库头文件
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#endif

ls(默认查看当前位置)

获得文件的属性

stat/lstat/fstat 获得文件属性

 #include <sys/types.h>

 #include <sys/stat.h>

 #include <unistd.h>

 fstat参数是文件描述符,不建议使用

int fstat(int fd, struct stat *buf);

 int stat(const char *path, struct stat *buf);

 int lstat(const char *path, struct stat *buf);

 如果path是符号链接,stat获得是目标文件的属性

                                  lstat获得的是链接文件的属性

参数1:文件名(绝对路径)

参数2:  struct stat * 获得文件属性之后,将文件属性的值放到buf所指的空间

返回值:若失败则返回-1

int lstat(const char *path, struct stat *buf);

ls -l(详细显示文件信息)

#include <stdio.h>

以某种格式显示在屏幕上

int printf(const char *format, ...);

printf(“%s/%s”,argv[1],pd->d_name);   “/home/linux/1.c“

以某种格式显示到文件中

int fprintf(FILE *stream, const char *format, ...);

fprintf(fp,“%s/%s”,argv[1],pd->d_name);

以某种格式存入到文件中去

char path_name[100];

int sprintf(char *str, const char *format, ...);

sprintf(path_name,”%s/%s”,argv[1],pd->d_name);

struct stat  
{   
    dev_t       st_dev;     /* ID of device containing file -文件所在设备的ID*/  
    ino_t       st_ino;     /* inode number -inode节点号*/    
    mode_t      st_mode;    /* protection -保护模式?*/    
    nlink_t     st_nlink;   /* number of hard links -链向此文件的连接数(硬连接)*/    
    uid_t       st_uid;     /* user ID of owner -user id*/    
    gid_t       st_gid;     /* group ID of owner - group id*/    
    dev_t       st_rdev;    /* device ID (if special file) -设备号,针对设备文件*/    
    off_t       st_size;    /* total size, in bytes -文件大小,字节为单位*/    
    blksize_t   st_blksize; /* blocksize for filesystem I/O -系统块的大小*/    
    blkcnt_t    st_blocks;  /* number of blocks allocated -文件所占块数*/    
    time_t      st_atime;   /* time of last access -最近存取时间*/    
    time_t      st_mtime;   /* time of last modification -最近修改时间*/    
    time_t      st_ctime;   /* time of last status change - 最近状态改变时间*/ 
};  

         

#include <stdio.h>
#include <string.h>
#include <time.h>
#include "dir.h"

int main(int argc, const char *argv[])
{
	//1.打开目录
	DIR *pdir=NULL;
	pdir=opendir(argv[1]);
	if(NULL==pdir)
	{
		perror("dir open error");
		return -1;
	}
	printf("dir open success\n");

	//2.目录读取
	struct dirent *pd=NULL;
	struct tm *pt=NULL;
	struct stat buf;
	char path_name[100]={'\0'};
	while(1)
	{
		memset(path_name,'\0',sizeof(path_name));
		//读取文件夹
		pd=readdir(pdir);
		if(NULL==pd)
		{
			break;
		}
		if(strncmp(pd->d_name,".",1)==0)
		{
			continue;
		}
		//printf("%s/%s",argv[1],pd->d_name);
		//3.通过文件名获得文件的属性
		//参数1:文件名(最好是绝对路径)
		//参数2:struct stat *
		//返回值:失败则返回-1
		sprintf(path_name,"%s/%s",argv[1],pd->d_name);
		if(lstat(path_name,&buf)<0)
		{
			perror("lstat error");
			return -1;
		}
		//printf("lstat success\n");
		//显示文件大小
		printf("%20ld",buf.st_size);
		//获得当地时间
		pt=localtime(&buf.st_atime);
		//显示当地时间,月 日 时 分
		printf("  %02d %02d %02d:%02d",pt->tm_mon+1,pt->tm_mday,pt->tm_hour,pt->tm_min);
		//显示文件名字
		printf("%20s",pd->d_name);
		printf("\n");
	}
	printf("\n");

	//3.关闭目录
	closedir(pdir);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值