嵌入式学习第十六天--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