day01
主要内容:
linux系统下一切皆文件
标准IO---标准库
文件IO---系统调用
制作库---静态库、动态库
基本概念:
标准I/O:
文件:一组相关数据的有序集合。
文件名:这个数据集合的名称。
文件类型:lsp-bcd
系统调用
用户空间进程访问内核的接口
把用户从底层的硬件编程中解放出来
极大的提高了系统的安全性
使用户程序具有可移植性
是操作系统的一部分
库函数
库函数为了实现某个功能而封装起来的API集合
提供统一的编程接口,更加便于应用程序的移植
是语言或者应用程序的一部分
文件指针:每个被使用的文件都在内存中开辟一个区域,用来存放文件的有关信息,这些信息是保存在一个结
构体类型的变量中,该结构体类型是由系统定义的,取名为FILE
FILE *
流(stream)
定义:所有的I/O操作仅是简单的从程序移进或者移出,这种字节流,就称为流。
分类:文本流/二进制流。
例如:2001
文本流表示为: 50 48 48 49
二进制流表示为:00000111 11010001
stdin:标准输入
stdout:标准输出
stderr:标准错误输出
行缓存
(1)行缓存--printf()
刷新行缓存区的条件
1、换行符
2、程序正常结束
3、缓存满了自动刷新--1024字节
4、fflush()刷新缓存
#include <stdio.h>
函数原型:int ffluh(FILE *stream);
参数:stream:文件流
(2)全缓存--文件(常用)
刷新全缓存的条件:
1、程序正常结束
2、缓存满了也自动刷新--4096字节
3、fflush刷新缓存
(3)无缓存--标准错误输出perror()
(4)用户自己设计缓存:
#include <stdio.h>
函数原型:int setvbuf(FILE *stream, char *buf, int mode, size_t size);
参数:
stream:文件流
buf:用户自己的缓存区,如果填写NULL,默认了多少就开多少(计算机)
mode:选择缓存的方式
_IONBF unbuffered--无缓存
_IOLBF line buffered--行缓存
_IOFBF fully buffered--全缓存
size:缓存大小
返回值:成功返回0,失败返回errno
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{
char buf[2000]={0};
setvbuf(stdout,buf,_IOLBF,2000);
for(int i=0;i<1025;i++)
{
printf("1");
}
while(1);
return 0;
}
1.标准IO的函数接口:
fopen()–打开一个文件
头文件:#include <stdio.h>
函数原型:FILE *fopen(const char *pathname, const char *mode);
pathname:文件的路径,如果只写文件名,默认在当前路径下
mode:打开的方式
r:只读,从文件的开头开始读
r+:可读可写,从文件开头(光标的位置,每操作一次,光标向后移动一位)开始操作
w:只写,从文件的开头开始操作,如果没有这个文件会创建,若文件存在则文件长度清为0
w+:可读可写,从文件的开头开始操作,如果没有这个文件会创建,若文件存在则文件长度清为0
a:只写,从文件的末尾开始操作,如果没有这个文件会创建
a+:可读可写,写从文件的末尾开始操作,读一般从文件开头开始操作,如果没有这个文件会创建
返回值:
成功返回文件流,失败返回NULL
1. fgetc()–得到一个文件的字符-fputc()–文件的输入输出
fgetc()--得到文件的一个字符
#include <stdio.h>
函数原型:int fgetc(FILE *stream);
参数:
stream:文件流
返回值:成功返回获取的文件的字符,失败返回的是EOF(宏定义)
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("2.c","r");
if(NULL == fp)
{
perror("open:");
return -1;
}
char c;
c = fgetc(fp);
printf("c=%c\n",c);
return 0;
}
fputc()--输入文件的字符
头文件:#include <stdio.h>
函数原型:int fputc(int c, FILE *stream);
参数:
c:输入文件的字符
stream:文件流
返回值:成功:返回写入文件的字符的ASCII码值,失败时,返回EOF(-1)
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("2.c","r+");
if(NULL == fp)
{
perror("open:");
return -1;
}
char c;
c = fgetc(fp);
printf("c=%c\n",c);
fputc('a',fp);
return 0;
}
2.fgets()–fputs()–文件的字符串的输入输出
fgets()--获取文件的字符串
#include <stdio.h>
函数原型:char *fgets(char *s, int size, FILE *stream);
参数:
s:缓存区,存放得到的文件内容
size:得到文件内容的大小
stream:文件流
成功返回s的首地址,失败返回NULL
注意:默认得到的字符串最后有'\0',遇到换行(回车)结束获取
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("2.c","r+");
if(NULL == fp)
{
perror("open:");
return -1;
}
char buf[128]={0};
fgets(buf,5,fp);
puts(buf);
return 0;
}
fputs()--往文件输出字符串
#include <stdio.h>
函数原型:int fputs(const char *s, FILE *stream);
参数:缓存区,给文件输入的内容
stream:文件流
返回值:成功返回非负整数,失败返回EOF
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("2.c","w+");
if(NULL == fp)
{
perror("open:");
return -1;
}
char buf[128]={0};
//fgets(buf,100,fp);
//puts(buf);
fgets(buf,128,stdin);//gets()
fputs(buf,stdout);//puts()
int ret = fputs(buf,fp);
printf("ret = %d\n",ret);
return 0;
}
练习:完成cp的功能
eg1:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp1 = fopen("2.c","r");
FILE *fp2 = fopen("3.c","w");
if(NULL == fp1)
{
perror("open:");
return -1;
}
char c=0;
while(1)
{
c = fgetc(fp1);//获取第一个文件的内容
if(c == EOF)
break;
fputc(c,fp2);//输出到第二个文件
}
return 0;
}
eg2:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp1 = fopen("2.c","r");
FILE *fp2 = fopen("3.c","w");
if(NULL == fp1)
{
perror("open:");
return -1;
}
char buf[128]={0};
while(1)
{
if(fgets(buf,128,fp1)==NULL)
break;
fputs(buf,fp2);//输出到第二个文件
}
return 0;
}
3.fread()-fwrite()–文件的输入输出
fread()--读取文件的内容
头文件:#include <stdio.h>
函数原型:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
ptr:缓冲区,用来存放读取的内容
size:每次读取内容的字节个数,一般填写1,一个字节一个字节的读取
nmemb:读取内容的大小
strem:文件流
返回值:成功返回读取内容的字节个数,一般填写1,一个字节一个字节读取
fwrite()--往文件里面写入内容
头文件:#include <stdio.h>
函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
参数:
ptr:缓冲区,用来存放读取的内容
size:每次写入内容的字节个数,一般填写1,一个字节一个字节的读取,失败返回0
nmemb:写入内容的大小
strem:文件流
返回值:成功返回读取内容的字节个数,一般填写1,一个字节一个字节读取,失败返回0
总结:
名称 | 功能 | 参数个数 | 返回值 |
---|---|---|---|
fopen | 打开一个文件 | 2 | 成功返回文件流,失败返回NULL |
fgetc | 得到一个文件的字符 | 1 | 成功返回获取的文件的字符,失败返回的是EOF(宏定义) |
fputc | 向文件输入一个字符 | 2 | 成功:返回写入文件的字符的ASCII码值,失败时,返回EOF(-1) |
fgets | 获取文件的字符串 | 3 | 成功返回s的首地址,失败返回NULL |
fouts | 往文件输入字符串 | 2 | 返回值:成功返回非负整数,失败返回EOF |
fread | 读取文件的内容 | 4 | 成功返回读取内容的字节个数,一般填写1,一个字节一个字节读取,失败返回0 |
fwrite | 往文件里1写入内容 | 4 | 成功返回读取内容的字节个数,一般填写1,一个字节一个字节读取,失败返回0 |
2.光标的操作:
#include <stdio.h>
1.函数原型:int fseek(FILE *stream,long offset,int whence);
功能:重定义光标
参数:
stream:文件流
offset:光标的偏移量
whence:起始位置(光标从哪个位置开始移动)
SEEK_SET--文件的开头
SEEK_CUR--光标当前位置
SEEK_END--文件的末尾
例如:
fseek(fp,10,SEEK_SET)--从文件的开头往后偏移10byte的位置
fseek(fp,-10,SEEK_END)--从文件的末尾往前偏移10byte的位置
fseek(fp,0,SEEK_SET)--不管光标在哪儿,一定回到文件开头
fseek(fp,0,SEEK_END)--不管光标在哪儿,一定回到文件末尾
返回值:成功返回0,失败返回-1
2.函数原型:long ftell(FILE *stream)--获取光标的偏移量
参数:
stream:文件流
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("2.c","r+");
if(NULL == fp)
{
perror("fopen");
return -1;
}
char buf[128]={0};
int ret = fread(buf,1,32,fp);
printf("ret = %d\n",ret);
printf("buf:\n%s\n",buf);
int size = ftell(fp);//获取光标的偏移量
printf("size=%d\n",size);
fseek(fp,0,SEEK_SET);//光标回到文件开头
fwrite(buf,1,32,fp);
return 0;
}
3.函数原型:void rewind(FILE *stream);
4.函数原型:int fgetpos(FILE *stream, fpos_t
*pos);
5.函数原型:int fsetpos(FILE *stream, const fpos_t
*pos);
3.flose()–文件的关闭
练习:文件的算法加密
比如源文件中放的是abcdef,加密(算法假设每个数据都+1)之后–>bcdefg
#include <stdio.h>
//加密
int mylock(char *filename)
{
FILE *fp = fopen(filename,"r+");
if(NULL == fp)
{
perror("open");
return -1;
}
char buf[1024]={0};
//读取文件的内容
int size = fread(buf,1,1024,fp);//此时光标在文件末尾
//算法加密
int i;
for(i=0;i<size;i++)
{
buf[i] += 10;
}
//移动光标回到文件开头
fseek(fp,0,SEEK_SET);
//把加密后的buf写入到原文件
fwrite(buf,1,size,fp);
fclose(fp);
}
//解密
int unlock(char *filename)
{
FILE *fp = fopen(filename,"r+");
if(NULL == fp)
{
perror("open");
return -1;
}
char buf[1024]={0};
//读取文件的内容
int size = fread(buf,1,1024,fp);//此时光标在文件末尾
//算法加密
int i;
for(i=0;i<size;i++)
{
buf[i] -= 10;
}
//移动光标回到文件开头
fseek(fp,0,SEEK_SET);
//把加密后的buf写入到原文件
fwrite(buf,1,size,fp);
fclose(fp);
}
int main(int argc, char *argv[])
{
puts("请选择你要操作的文件:");
char filename[32]={0};
gets(filename);
puts("请选择你的操作:1--加密,2--解密");
int a;
scanf("%d",&a);
if(a == 1)
mylock(filename);
else
unlock(filename);
return 0;
}
练习:
1、查找单词:
实现文本文件单词查找,输出单词出现的位置
void get_pos(char *filename,char *word)
{
FILE *fp = fopen(filename,"r");
char buf[1024]={0};
int size = fread(buf,1,1024,fp);
int count = 1;
int i,pos=0;
for(i=0;i<size;i++)
{
pos++;
if(strncmp(word,&buf[i],strlen(word))==0)
{
printf("该单词在第%d行,第%d个\n",count,pos);
}
if(buf[i] == '\n')
{
pos=0;
count++;
}
}
}
2、查看内容:
输入一个行数,实现文件对应行数的查看
例如: 输入10,查看前10行 输入-10,查看后10行
void mycat(char *filename,int line)
{
char buf[1024]={0};
int file_line=0;
int i;
FILE *fp = fopen(filename,"r");
if(line>0)
{
for(i=0;i<line;i++)
{
fgets(buf,1024,fp);
printf("%s",buf);
}
}else
{
//求行数
while(fgets(buf,1024,fp)!=NULL)
{
file_line++;
}
fseek(fp,0,SEEK_SET);
for(i=0;i<file_line+line;i++)
{
fgets(buf,1024,fp);
}
for(i=file_line+line;i<file_line;i++)
{
fgets(buf,1024,fp);
printf("%s",buf);
}
}