当前位置: 首页 > article >正文

嵌入式学习第十六天--stdio(二)

文件打开

open函数     

#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_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
    

                        

库函数 和 系统调用         


close 关闭:


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


  
文件描述符:


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


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

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


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

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

缓存的设计


缓存 设计的目的提高效率  
本质上来说 ---缓存其实就是一块内存空间 

行缓冲:

1k, terminal,主要用于人机交互stdout
    
    缓存区满或者遇到\n刷新    1024
                行缓存多是关于终端的一些操作
                1.遇到\n刷新
                2.缓存区满刷新
                3.程序结束刷新
                4.fflush刷新  fflush(stdout);


                
全缓冲

4k,主要用于文件的读写
    缓存区满刷新缓存区 4096
            对普通文件进行标准IO操作,建立
            的缓存一般为全缓存
            刷新条件:
                1.缓存区满刷新
                2.程序结束刷新
                3.fflush来刷新  fflush(fp);


无缓冲

0k  主要用于出错处理信息的输出 stderr 
    不对数据缓存直接刷新
    printf();==>>stdout 
    fprintf(strerr,"fopen error %s",filename);
                界面交互    出错处理
使用gdb查看,FILE结构体,或使用写入数据测试缓冲区。
缓冲区的大小是可以设置

linux下缓存设计:
交互 --- 行缓存 
文件 --- 全缓存 
出错 --- 不缓存 

./a.out < main.c   //< 表示输入重定向 
./a.out > main.c   //> 表示输出重定向 

fread/fwrite //二进制读写函数 按对象读写

#include <stdio.h>
size_t  fread(      void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:
     二进制流的读/写
参数:
   @ptr   表示存放数据的空间的地址 
   @size  要操作的单个元素(对象)的大小
   @nmemb 要操作的元素(对象)的个数 
   @stream 要操作的文件 
返回值:
   成功 返回的是 成功操作到的对象的个数 
   失败 0
     到达文件结尾 返回 0
     
应用:
   主要 应用在 文件中 有固定格式的  场景 
   
   

   
  
eg:
   将3个学生的信息,写到文件中 之后,从文件中读出学生信息,打印 

#include<stdio.h>
struct student
{
	char name[10];
	int sno;
	float score;
};

int main(int argc, const char *argv[])
{
	FILE* fp = fopen(argv[1],"r+");
	if(argc!=2)
	{
	printf("Usage:%s<filename>",argv[0]);
	return -1;
	}
	if(fp==NULL)
	{
		perror("fail open");
		return -1;
	}

	struct student s[3]={"tom",110,99.7,
							"henry",111,99.8,
							"jery",112,99.2};

	fwrite(s,sizeof(struct student ),3,fp);
	rewind(fp);
	struct student s1[3];
	fread(s1,sizeof(struct student ),3,fp);
	int i=0;
	for(i=0;i<3;i++)
	{
		printf("%s\n",s[i].name);
		printf("%d\n",s[i].sno);
		printf("%f\n",s[i].score);
	}
	fclose(fp);
	return 0;
}


   
   
文件偏移量:


   rewind


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


   功能:
       定位文件 
   参数:
      @stream  表示要操作文件 
      @offset  表示文件偏移量 
      @whence  定位的参考点 
               SEEK_SET //相对于文件开头的 
                  offset >=0 
               SEEK_CUR //相对于当前位置
                  offset>=0
                  offset<0   //不能超过这个文件开头
               SEEK_END //相对于文件末尾 
                  offset < 0  //不能超过这个文件开头
                  offset >= 0 //可以  --- 创建 空洞 文件
   返回值:
      成功 0
      失败 -1
      
                             
     fseek(fp,100,SEEK_SET);//
     fseek(fp,0,SEEK_SET);//定位到开头 
     fseek(fp,0,SEEK_END);//定位到末尾
     
     创建空洞文件: 
     1.做偏移 
     2.写操作 

#include<stdio.h>
int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("Usage:%s<filename><filename>\n",argv[0]);
		return -1;
	}
	FILE *fp1=fopen(argv[1],"r+");
	fseek(fp1,0,SEEK_END);
	long len = ftell(fp1);
	fseek(fp1,0,SEEK_SET);

	FILE *fp_h = fopen(argv[2],"w+");
	if(fseek(fp_h,len-1,SEEK_END)!=0)
	{
		perror("fseek fail");
		return -1;
	}
	fputc('\0',fp_h);
	fseek(fp_h,0,SEEK_SET);
	char buf[100];
	//char buf[len];
	//ret=fread(buf,sizeof(buf),1,fp1);
	int ret;
	while(ret=fread(buf,sizeof(char),sizeof(buf),fp1))
	{
		fwrite(buf,sizeof(char),ret,fp_h);
	}
	fclose(fp1);
	fclose(fp_h);
	return 0;
}


     
     //空洞文件中的数据 ,都是0
     


   long ftell(FILE*stream);


   功能:
       获得当前文件的偏移量 
   void rewind(FILE*stream);
   功能:
       将文件偏移量设置到文件开头 
       
       
  获得某个文件的大小:
  1. fseek(fp,0,SEEK_END);//定位到末尾
  2. long len =ftell(fp); 
  
 
练习:
   cp   

#include<stdio.h>
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
	printf("Usage:%s<filename><filename>",argv[0]);
	}
	FILE* fp = fopen(argv[1],"r+");
	FILE* fp1 = fopen(argv[2],"r+");
	char buf[1000];
	int ret;
	while(ret= fread(buf,sizeof(char),1000,fp))
	{
		fwrite(buf,sizeof(char),ret,fp1);
	}
	fclose(fp);
	fclose(fp1);	
	return 0;
}


    

   

   
eg:
   1.统计文件中英文字符出现的次数 

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc, const char *argv[])
{
	if(argc!=2)
	{
		printf("Usage:%s<filename>",argv[0]);
		return -1;
	}
	if(argv[1]==NULL)
	{
		perror("fail open");
		return -1;
	}
	int fd = open(argv[1],O_RDONLY);
	unsigned char ch;
	int cnt[26]={0};
	while(read(fd,&ch,1)!=0)
	{
		if(ch>='a'&&ch<='z')
		{
			cnt[ch-'a']++;
		}
		else if(ch>='A'&&ch<='Z')
		{
			cnt[ch-'A']++;
		}
	}
	int i;
	for(i=0;i<26;i++)
	{
		printf("%c:%d\n",i+'a',cnt[i]);
	}
	return 0;
}


   2.
   bmp图片:
   [54头信息]
   [图像信息] //bmp图像信息 --- 原始图像 

#include<stdio.h>
//-/a.out 0.bmp 2.bmp 3.bmp
int main(int argc, const char *argv[])
{
	if(argc != 4)
	{
    printf("usage: %s <src0.bnp> <src2.bnp> <dest.bnp>\n",argv[0]);
    return -1;
	}
    FILE *fp1 = fopen(argv[1],"r");
    FILE *fp2 = fopen(argv[2],"r");
    FILE *fp3 = fopen(argv[3],"w");
    if (fp1 == NULL || fp2 == NULL || fp3 == NULL)
	{
    perror("fopen fail");
    return -1;
	}
    unsigned char head1[54];//
    unsigned char head2[54];//
    unsigned char body1[600*800*3];//
    unsigned char body2[600*800*3];//
    fread(head1, sizeof(unsigned char),54,fp1);
    fread(body1,sizeof(unsigned char),600*800*3,fp1);
    fread(head2,sizeof(unsigned char),54,fp2);
    fread(body2,sizeof(unsigned char),600*800*3,fp2);
    int i=0;
	for(i=0;i<600*800*3;i++)
	{
		if (!(body1[i] == 255&&body1[i+1]==255&&body1[i+2]==255))
		{
			body2[i] =body1[i];
			body2[i+1] = body1[i+1];
			body2[i+2] =body1[i+2];
		}
	}
    fwrite(head2,sizeof(char),54,fp3);
    fwrite(body2,sizeof(char),600*800*3,fp3);
    fclose(fp1);
    fclose(fp2);
    fclose(fp3);
    return 0;
}

运行结果:
   

1.bmp

2.bmp

t.bmp


http://www.kler.cn/a/551658.html

相关文章:

  • SQL进阶技巧:如何统计用户跨端消费行为?
  • STM32 HAL库USART串口中断编程:环形缓冲区防止数据丢失
  • 【开源】基于SSM框架网上招聘系统(计算机毕业设计)+万字毕业论文+远程部署+ppt+代码讲解 ssm592
  • android studio 界面启动模拟器无反应——从命令行启动模拟器
  • LLaVA-Mini部署教程 :模态预融合与视觉符元压缩,重新定义图像视频理解边界!
  • 调试变量的变化 vs数据断点调试
  • 核函数简述
  • 【MySQL排错 】mysql: command not found 数据库安装后无法加载的解决办法
  • 高效执行自动化用例:分布式执行工具pytest-xdist实战
  • leetcod20-有效的括号
  • 基于机器学习的医疗图像分析:从图像识别到精准诊断
  • 关于JavaScript中的事件
  • 设计模式-结构型-享元模式
  • 【Python pro】基本数据类型
  • CentOS/RHEL如何更换国内Yum源
  • 深度学习笔记之自然语言处理(NLP)
  • 推荐几款较好的开源成熟框架
  • vue中为什么在实现双向绑定时
  • BSD协议栈:UDP输入
  • LLM 架构