基础概念
文件: 一组相关数据的集合。
文件名: 这个集合的名称。
Linux系统下文件的类型:
B -- block -- 块设备文件 -- eg:硬盘这一类的存储设备(一次性读一堆)
C -- character -- 字符设备文件 --eg:鼠标键盘(一次性读一个字符)
D -- directory(目录) -- 目录文件 -- eg:文件夹
- -- regular -- 普通文件
L --symbolic link(符号链接) – 软连接文件 --eg:相当于windows下的快捷方式
P --pipe(管道) -- 管道文件 --eg:用于进程间通信(传输数据的)
S -- socket(套接字)-- (本地)套接字文件 –eg:网络部分用到
文件设计的思想:一切皆文件。
总结:
实现用户应用程序的 两条途径:
- 直接使用操作函数
- 使用”库函数”
文件编程
库函数的方式
库函数--- c库中的相关文件操作的函数 – 标准IO(input output)
标准IO提供的函数:
1.打开
fopen //file open
FILE *fopen(const char *pathname, const char *mode);
功能:
流打开函数(打开文件) //流
参数:
@pathname 要打开的文件的名字 //形式 字符串形式 eg:“1.txt”
@mode 打开文件模式
r 只读
r+ 读写
w 只写 文件已存在,此时截断为0长度
文件不存在 则会创造该文件
a 追写 本质上是一个写的操作,如果文件存在就在末尾写
文件不存在,则创建文件
a+追加读写 文件存在 就会在开头进行读 文件末尾进行写
文件不存在 则创建文件
返回值:
成功 返回 FILE* //文件指针 (流指针)
FILE* 实际上代表的就是打开的文件
失败 返回 NULL
同时errno(全局错误码变量)
被设置来表明错误原因
Perror( ) ;
//作用:打印出错误原因(背后使用实际上errno)
用法:
perror(“用户自定义信息”)
输出定义的那句话,后面加上: 输出错误信息。
2.读和写
按字符读写 fgetc/fputc
fgetc int fgetc( FILE* stream)
功能:从流中读取下一个字符,并将读到的无符号字符型强转为int型返回
参数:@FILE *stream
返回值: 成功 读取的无符号字符转为int型
失败 EOF(-1)
fputc int fputc (int c, FILE *stream);
功能: 向文件中输出一个字符
参数: @c 保存字符的一块空间
@steam 要输出的文件
返回值:成功 返回写入的字符 'c'
失败 返回 EOF
(通常是 -1)。
按字符串读写 fgets/fputs
fgets char *fgets(char *s, int size, FILE *stream);
功能: 从文件中读取字符串
参数: @ s 保存字符串的一块内存空间
@size 一次期望读取的字节个数
@stream 要读取的文件
返回值: 成功 返回s
失败 返回NULL
fputs int fputs(const char *s, FILE *stream);
功能: 输出s字符串到端流中(不会输出/0)
参数: @ s 要输出的字符串
@ stream 要输出到的文件
返回值: 成功 非负数
失败 EOF
注意:在用fputs拷贝二进制文件 有问题
原因:fputs输出时,遇到‘\0’就结束了
按对象读写 fread/fwrite
Size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件中读取数据
参数:@ ptr 存放数据的内存空间的地址
@size 读取的单个元素的大小
@nmemb 读取的元素的个数
@stream 要读取的文件
返回值:
成功 返回读取到的元素的个数
失败 返回0
Size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:往文件中写入数据
参数:
@ptr 存放数据的内存空间的地址
@size 单个元素的大小
@nmemb 要写入元素的个数
@stream 要写入的文件
返回值:
成功 返回写入的元素的个数
返回 返回0
fread 和 fwrite 更多的的情况时,适用于文件中有固定的格式的这种操作。
3.关闭
Fclose // file close
Int fclose(FILE *stream):
- 刷新流
- 关闭流,关闭底层文件描述
注意:不能多次关闭同一个文件
操作系统默认 已经打开了三个文件(关联到三个流)
标准输入 – stdin -0
标准输出 –stdout -1
标准出错 –stderr -2
用fwrite 和 fread 编写一个拷贝程序。
代码练习:
e1.通过fopen,fgetc,fputc,一个程序 实现cp的功能
#include<stdio.h>
int main(int argc, const char *argv[])
{
if(argc != 3)
{
printf("usage: %s <src fil> <dest file>\n",argv[0]);
return -1;
}
FILE *src = fopen(argv[1],"r"); //打开源文件 只读
FILE *dest = fopen(argv[2],"w"); //打开目标文件 只写
if(src == NULL || dest == NULL)
{
perror("open fail");
return -1;
}
int ch = 0;
while((ch = fgetc(src)) != EOF) //一直读取源文件直到ch 为 EOF
{
fputc(ch,dest); //ch 返回值为读到的字符 将字符写入 dest目标文件
}
fclose(src);
fclose(dest);
return 0;
}
e2. 用fgets来实现系统的cat功能
#include<stdio.h>
int main(int argc, const char *argv[])
{
if(argc != 2)
{
printf("usage: %s <filename> \n",argv[0]);
return -1;
}
FILE *fp = fopen(argv[1],"r");
if(fp == NULL)
{
perror("open fail");
return -1;
}
int ch = 0;
while((ch = fgetc(fp)) != EOF)
{
// printf("%c",ch); //stdout 为显示终端的标识符
fputc(ch,stdout);
}
fclose(fp);
return 0;
}
e3.用 fgets 时编写一个函数来计算文章行数
#include<stdio.h>
#include<string.h>
int rows_file(char *c) //函数功能 判断是否换行
{ //查找传进来的字符串最后一个字符是否为'\n'
int n = strlen(c);
if(c[n - 1] == '\n')
{
return 1;
}
return 0;
}
int main(int argc, const char *argv[])
{
if(argc != 2)
{
printf("usage: %s <src file>\n",argv[0]);
return -1;
}
FILE *src = fopen(argv[1], "r");
if(src == NULL )
{
perror("cat fail");
return -1;
}
int counter = 0;
char buf[5];
while(fgets(buf,sizeof(buf),src) != NULL) //一次读取sizeof(buf)个字符装进buf里
{ //直到读完文章返回NULL
printf("%s",buf);
counter += rows_file(buf); //统计行数
}
printf("%d\n",counter);
fclose(src);
return 0;
}