嵌入式学习第十七天--fileio

fileIo


文件操作:


         缓存           操作对象                具体操作
标准IO  全缓存/行缓存   文件指针(流指针)FILE *  1.打开 --fopen  
(库函数)                                        2.读写 
                                                  fgetc/fputc 
                                                  fgets/fputs 
                                                  fread/fwrite 
                                                3.关闭 
                                                  fclose 
                                                4.定位 
                                                  fseek/ftell/rewind 
                                                  空洞文件 
                                                                          
                                                                        
                                          
文件IO  不带缓存       文件描述符 (整数)        1.打开 --open 
(系统调用)                                      2.读写 --read/write
                                                3.关闭 --close 
                                                4.定位 --lseek 
    

                                            
打开文件:


open函数     

#include
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_APPEND  //追加 
            O_CREAT   //文件不存在 创建 
            O_TRUNC   //文件存在  截短为0 
  @mode     一般不用
            当flags中使用了 O_CREAT 时,需要指定 mode   
            mode 0777
                 0666
                 0444                  
返回值:
  成功 文件描述符
  失败 -1 && errno会被设置 
  
  
fopen             open
r                O_RDONLY 
r+               O_RDWR

w                O_WRONLY|O_CREAT|O_TRUNC 
w+               O_RDWR|O_CREAT|O_TRUNC

a                O_WRONLY|O_APPEND|O_CREAT
a+               O_RDWR |O_APPEND|O_CREAT

FILE * fopen(const char *pathname,const char *mode)
{
   ...
   if (strcmp("r",mode))
       open(pathname,O_RDONLY);
}


文件创建好后的权限:
  a.指定的mode 
  b.umask  (掩码) //二进制位 --- 遮住 

  最终文件的权限 = ~umask & mode
  
  0  7   7   7 
    111 111 111  mode
  0 000 000 010
    111 111 101 ~umask 
    ------------
    111 111 101 
     7  7   5
                          

关闭文件:



int close(int fd);


功能:
   关闭文件描述符
   以便 再次使用 
参数:
  @fd  要关闭的文件描述符
返回值:
  成功 0
  失败 -1 
  


文件描述符:


1.非负整型数值 
2.分配原则
  最小未使用   
3.范围 
  0~1023 
  


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

#include
功能: 
    从fd中读数据 ,存到 buf中 
参数:
   @fd 要读取的文件 
   @buf 存放读取到的数据的 内存空间 
   @count 一次要读取的数量(字节)
返回值:
   成功 表示成功读到的字节数 
   失败 -1 && errno 
   
   读取结束:
      0 表示到达文件结尾


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

#include
功能: 
    把buf中 写到fd中 
参数:
   @fd    要写入的文件 
   @buf   存放数据的 内存空间 
   @count 一次要写入的数量(字节)
返回值:
   成功 表示成功写入的字节数 
   失败 -1 && errno 
   

练习:
   cat  //文件IO 实现 

1.结果输出到stdin

#include
#include
#include
int main(int argc, const char *argv[])
{
	int fp;
	fp = open(argv[1],O_RDONLY);
	char buf[10];
	int ret=0;
	while((ret=read(fp,buf,sizeof(buf)-1))!=0)
	{
		buf[ret]='\0';
		printf("%s",buf);
	}
	close(fp);


	return 0;
}

2.结果复制到文件

#include
#include
#include
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("Usage:%s",argv[0]);
		return -1;
	}
	int fp1 = open(argv[1],O_RDONLY);
	int fp2 = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
	if(fp1<0||fp2<0)
	{
		perror("fail open");
		return -1;
	}
	char buf[10];
	int ret=0;
	while(ret=read(fp1,buf,sizeof(buf)))
	{
		write(fp2,buf,ret);
	}
	close(fp1);
	close(fp2);


	return 0;
}


   
 

lseek 

off_t lseek(int fd, off_t offset, int whence);
功能:
     重新定位文件偏移量 
参数:
    @fd      要定位的文件 
    @offset  偏移量 
    @whence  参考点 
               SEEK_SET //相对于文件开头的 
                  offset >=0 
               SEEK_CUR //相对于当前位置
                  offset>=0
                  offset<0   //不能超过这个文件开头
               SEEK_END //相对于文件末尾 
                  offset < 0  //不能超过这个文件开头
                  offset >= 0 //可以  --- 创建 空洞 文件
   
返回值:
   成功 从头的偏移量
   失败  -1 && errno

lseek(fd,0,SEEK_SET); //定位到文件开头 
lseek(fd,0,SEEK_END);

获得文件长度:
off_t len = lseek(fd,0,SEEK_END); //off_t <=> long int

eg:
   创建空洞文件 
   给定一个文件,创建一个同样大小的空洞文件 

#include
#include
#include
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("Usage:%s",argv[0]);
		return -1;
	}
	int fp=open(argv[1],O_RDONLY);
	if(fp<0)
	{
		perror("fail open");
		return -1;
	}
	int fp_h=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
	if(fp_h<0)
	{
		perror("fail open");
		return -1;
	}
	long int len =lseek(fp,0,SEEK_END);
	lseek(fp_h,len-1,SEEK_SET);
	write(fp_h,"",1);
	close(fp);
	close(fp_h);
	return 0;
}


   

   
注意:
    1、不支持O_APPEND的追加模式,无法生成空洞文件。
    2、lseek函数执行失败,文件指针还在偏移前的位置。
    3、lseek函数在设备文件上偏移无效。 /dev/video0 
    4、fifo,socket 也不支持lseek的操作。
   
   


对比:


库函数: //标准IO
     优点:
         a.方便,功能多 
         b.可移植性好 
           标准 
     不足:
         c.可能存在 安全性 隐患


系统调用:
     优点:
         a.使用起来,简单 ,功能简单
         b.安全性高 
         c.设备文件 ---- 文件IO      ///dev/video0 ----> fopen();     
     缺点:
         c.很多复杂功能需要自己封装设计
         d.可移植性差 

 


标准IO 操作中 ---系统调用的函数 

fdopen()  //将fd 转换  成 FILE *
fileno()  //将FILE *转换 为 fd


FILE *fdopen(int fd,const char *mode);


功能:
   将fd 转换  成 FILE * 
参数:
   @fd    要操作fd
   @mode  打开的模式
返回值: 
   成功 FILE *
   失败 NULL
   
  


int fileno(FILE *stream);


功能:
    将FILE *转换 为 fd
参数:
   @stream  要转换流指针 
返回值:
   成功 fd 
   失败 - && errno   
  eg:
  fd = open("1.txt",O_RDONLY);
  FILE *fp = fdopen(fd,"a");
   
   
使用的选择:
  标准IO   --- 可移植性 如果操作只是文本数据 
  文件IO   --- 安全性  操作的是硬件 ---文件IO
  

  
操作目录:


目录也是一种文件 
类似 标准IO 

//1.打开 
opendir
//2.读写
readdir
//3.关闭 
closedir

 


DIR *opendir(const char *name); 


功能:
    打开目录,关联一个目录流
参数:
  @name  要打开的目录名 
返回值:
  成功 返回DIR *
  失败 NULL & errno
  


struct dirent *readdir(DIR *dirp);


功能:
    读取目录项 
参数:
   @dirp 目录流指针 
返回值:
   成功 struct dirent *
   失败 NULL && errno
struct dirent 
{
    ino_t d_ino; /* Inode number */ 
    off_t d_off; /* Not an offset; see below */
    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]; /* Null-terminated filename */
}

注意:
   读到文件末尾 NULL
   
   
   int closedir(DIR *dirp);


   功能:
      关闭目录流
   参数:
      @dirp --- 目录流指针 
   返回值:
      成功 0
      失败 -1 &&errno 
      
eg:
    实现ls 

#include
#include
int main(int argc, const char *argv[])
{
	DIR * dir = opendir(argv[1]);
	if(dir == NULL)
	{
		perror("fail open ");
		return -1;
	}
	struct dirent *pdir = NULL;
	while(1)
	{
		pdir=readdir(dir);
		if(pdir==NULL)
		{
			break;
		}
		if((pdir->d_name[0])!='.')
		printf("%s",pdir->d_name);
	}
	putchar('\n');
	closedir(dir);
	
	return 0;
}


eg:
   shell 
   给定一个目录,统计目录下的 普通文件 和 目录文件的个数

#include
#include
int main(int argc, const char *argv[])
{
	DIR * dir = opendir(argv[1]);
	if(dir == NULL)
	{
		perror("fail open ");
		return -1;
	}
	int nr=0;
	int ndir=0;
	struct dirent *pdir = NULL;
	while(1)
	{
		pdir=readdir(dir);
		if(pdir==NULL)
		{
			break;
		}
		if((pdir->d_type)==DT_REG)
		{
			nr++;
		}
		else if((pdir->d_type)==DT_DIR)
		{
			ndir++;
		}
	}
	printf("nr=%d\nndir=%d",nr,ndir);
	closedir(dir);
	
	return 0;
}


   


chdir


chdir ("/home/linux"); "../../"
fopen("1.mp4")
int chdir(const char *path);// /home/linux
功能:
    改变当前程序的工作路径
参数:
    path:改变到的路径
返回值:
    成功 返回0
    失败 返回-1


/home/linux/Desktop/Music
"file.txt"

chdir("/root");
"file.txt"

getcwd //pwd 


char *getcwd(char *buf, size_t size);
功能:
    获得当前的工作路径
参数:
    buf:保存工作路径空间的首地址
    size:保存路径空间的长度
返回值:
    成功返回包含路径空间的字符串首地址
    失败返回NULL

 

mkdir 


int a  =200;

int mkdir(const char *pathname, mode_t mode);//777  666 --x--x--x
功能:
    创建一个目录
    666-
参数:
    pathname:路径
    mode:
        mode & ~umask  0002
        
返回值:
    成功 返回0
    失败 返回-1
    


rmdir   rm -fr    rmdir


int rmdir(const char *pathname);
功能:
    删除一个空目录文件
参数:
    pathname:目录文件的名字
返回值:
    成功 返回0
    失败 返回-1

 

 


     
   

 

你可能感兴趣的:(linxu高级编程,学习,spring,java)