系统三种缓冲方式:
1.行缓冲,1k // | terminal 主要用于人机交互stdout
缓存区满或者遇到\n刷新 1024
满足以下条件时刷新:
遇到\n刷新
缓存区满刷新
程序正常结束刷新
Fflush刷新 fflush(stdout);
2.全缓冲,4k // 主要用于文件的读写
缓存区满刷新缓存区 4096
缓存区满刷新
程序结束刷新
fflush来刷新 fflush(fp)
3.无缓冲,0k //主要用于出错处理信息的输出 stderr
不对数据缓存直接刷新
Printf(); ==>>stdout
fprintf(strerr,”fopen error %s”,filename);
缓存的设计原则:
- 与终端关联的设备 ---行缓存
- 与普通文件关联 ---全缓存
- 出错处理 ---不缓存
重定向
> 输出重定向
< 输入重定向
printf():
int printf( const char *format, …);
int fprintf( FILE *stream, const char *format, …);
int sprint( char *str, const char *format,…);
Printf --- 格式化输出函数
Printf(“%o\n”,123);
Scanf --- 格式化输入函数
Scanf(“%o”,&a); 将输入转化为八进制输入到a中
fseek
Int fseek (FILE *stream, long offset, int whence);
功能:
设置文件偏移量
参数:
@stream –要定位的文件
@offset –偏移量的值
@whence –参考点
SEEK_SET 文件开头 offset值 不能是 负数
SEEK_CUR 当前位置 offset值 可正可负 但是不能超出范围
SEEK_END 文件末尾 offset值 可正可负
使用SEEK_END定位到文件末尾时,如果offset是正数,给文件扩容,
如果对空文件使用 fseek(,,SEEK_END) offset是正数时
则会把文件变为空洞文件 --- 提前抢占磁盘空间
返回值:成功 返回0
失败 返回-1 & errno会被设置
复制:
1.临时文件 --- 要占用大小
2.开始下载(复制)(创造目标文件时 并 占用磁盘空间)
使用 空洞文件 实现复制(模仿百度云下载)
创造一个目标的空洞文件
- 偏移
- 写操作
目标文件
- 获取源文件大小
fseek(fp_s,0,SEEK_END);
long len = ftell(fp_s); //源文件的大小
2.目标文件占空间
fseek(fp_d,len – 1, SEEK_SET);
fputc(‘\0’,fp_d);
总结:
标准IO --- 文件指针 流指针(操作对象 --- FILE *流指针)
1.打开
Fopen
2.读写
fgetc/fputc 单个字符
fgets/fputs 字符串
fread/fwrite 面向对象
3.关闭
fclose(fp);
4.定位
rewind(fp)重置流指针为文章开头
fflush(fp)释放缓存区到流指针
ftell(fp) 计算从文章开始 到 当前流指针位置的长度。(char)
fseek() 把流指针定位到指定位置
文件权限:
所有者 所属者 其他人
111 111 101 (有就是1 没有就是0)
7 7 5 (用八进制来表示 0775)
110 110 110 (0666)
代码练习
e1.在文件中间插入一个字符串,要求自己输入字符串和要插入的位置。
#include<stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{
if(argc != 2)
{
printf("Usage:%s <file name>!\n",argv[0]);
return -1;
}
FILE *fp = fopen(argv[1],"r+");
printf("Input a string: ");
char s[100];
fgets(s, sizeof(s), stdin);
//hello'\n''\0'
s[strlen(s) - 1] = '\0';
printf("input a offset:");
int n = 0;
scanf("%d", &n);
fseek(fp, 0, SEEK_END);
long len = ftell(fp);
char buff[len - n + 1 ];
fseek(fp,n,SEEK_SET);
fread(buff,sizeof(char),len - n , fp); // 从要插入的位置复制后面的字符
buff[len - n + 1] = '\0'; //在buff末尾补上'\0'
fseek(fp,n,SEEK_SET);
fwrite(s,sizeof(char),strlen(s),fp);
fwrite(buff,sizeof(char),strlen(buff),fp);
fclose(fp);
return 0;
}
e2.统计一个文章中小写字母的个数
#include<stdio.h>
int main(int argc, const char *argv[])
{
if(argc != 2)
{
printf("Usage: %s <file name>!\n",argv[0]);
return -1;
}
FILE *fp = fopen(argv[1],"r"); //打开文件
if(fp == NULL)
{
perror("open error!");
return -1;
}
int a[26] = {0};
int ch = 0;
while((ch = fgetc(fp)) != EOF) //遍历统计小写字母
{
if(ch >= 'a' && ch <= 'z')
{
a[ch - 'a'] += 1;
}
}
int i = 0;
for(i = 0; i < 26; ++i)
{
printf("%c = %d\n",(char)(i + 'a'), a[i]);
}
return 0;
}