文件操作(标准I/O,文件I/O):打开,创建,读写操作,标准I/O和文件I/O的区别
Linux系统下一切皆文件。
1.标准I/O(缓冲区文件操作)
接口:
类型 ANSI C标准文件操作管理
文件描述:
认识缓冲区
一块内存区,在输入输出设备和CPU间,用来缓存数据。
读写操作都要经过缓冲区满足一定条件(遇到’\n’通过相关函数)后进行真正的写入和读出标准输入/输出流:
程序开始运行时,会有3个默认打开的文件标识符
0:标准输入:stdin:STDIN_FILENO
系统分配为键盘
1:标准输出:stdout: STDOUT_FILENO
系统分配为显示器
2:标准错误:stderr: STERROR_FILONO
系统分配为显示器
fflush()//清理缓冲区的函数
fflush(stdin)
ffush(stdout)
FILE指针
定义
系统为打开文件建立的文件结构体,打开时返回来一个指针,程序通过指针获得文件信息,访问文件,关闭后,文件结构体被释放
ANSI c描述一个打开的文件,定义stdio.h
形式
struct _iobuf
{
char *_ptr;//当前缓冲区内容指针
int _cnt;//缓冲区还有多少个字符
char *_base;//缓冲区的起始地址
int _flag;//文件流的状态,是否错误或者结束
int _file;//文件描述符
int _charbuf;//双字节缓冲,缓冲2个字节
int _bufsiz;//缓冲区大小
char *_tmpfname;//临时文件名
};
typedef struct _iobuf FILE;
打开关闭
API
fopen
原型
FILE * fopen(const char * path,const char * mode);
功能
打开由path指定的一个文件
头文件
#include<stdio.h>
参数
path:带路径的文件名
mode打开方式
r
打开只读文件,该文件必须存在
r+
打开可读写的文件,该文件必须存在
w
打开只写文件,若文件存在则文件长度清为0,即会擦些文件以
前内容。若文件不存在则建立该文件。
w+
打开可读写文件,若文件存在则文件长度清为0,即会擦些文件
以前内容。若文件不存在则建立该文件。
a
以附加的方式打开只写文件。若文件不存在,则会建立该文件,
如果文件存在,写入的数据会被加到文件尾,即文件原先的内容
会被保留。
a+
以附加方式打开可读写的文件。若文件不存在,则会建立该文
件,如果文件存在,写入的数据会被加到文件尾后,即文件原先
的内容会被保留。
返回值
成功,返回操作文件的指针
失败,返回NULL
fclose
原型
int fclose(FILE *fp)
功能
关闭文件指针,释放资源
参数
fp: fopen返回的文件指针
返回值
成功返回 0
失败返回 -1
注意事项:
有没有这个文件
你要进行的操作
代码演示:
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
fp = fopen("hello.txt","r");
if(fp == NULL)
{
perror("fopen");//打印错误原因
return -1;
}
printf("打开文件成功\n");
fclose(fp);
return 0;
}
单个字符读写
API
fputc
原型
int fputc(int c, FILE *stream)
头文件
#include <stdio.h>
功能
写一个字符到文件中
参数
c:要写入的字符
stream:文件指针(要有可写权限)
返回值
成功:字符c
失败: EOF
fgetc
原型
int fgetc(FILE *stream);
头文件
#include <stdio.h>
功能
从文件中读一个字符
返回值
成功:返回读出的字符
失败: EOF
feof
原型
int feof(FILE *stream);
头文件
include <stdio.h>
功能
检查文件是否读取结束
参数
stream:指向待检查文件的指针
返回值
文件未结束: 0
文件已结束: 1
代码演示:
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
char ch;
fp = fopen("hello.txt","w+");
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("打开文件成功\n");
while(ch != '#')
{
fputc(ch,fp);
ch = getchar();
}
fclose(fp);//关闭后重新打开,移动光标
fp = fopen("hello.txt","r");//不能使用w,w+
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("打开文件成功\n");//重新打开,移动光标
ch = fgetc(fp);
while(!feof(fp))//文件未结束时候为0
{
putchar(ch);
ch = fgetc(fp);
}
fclose(fp);
return 0;
}
运行结果:
字符串读写
fgets
原型
char * fgets(char * s, int size, FILE * fp);
头文件
#include <stdio.h>
功能
从fp指向的文件中读出一行(最多size-1个字符) 直到出现换行字符、读到文件尾或是已读了size-1 个字符为止,写入s指向的缓冲区。
参数
s 保存读取到的字符
size 要读取的字符的个数
fp 为文件流指针
返回值
取成功,返回读取到的字符串,失败NULL
fputs
原型
int fputs(const char *s, FILE *fp)
功能:将字符串s写入fp指向的文件中
s: 要写入文件的缓冲区指针
fp:要写入的目标文件的流指针
代码演示:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
char w_buf[12] = "hello world";//12个
char r_buf[12];
memset(r_buf,0,sizeof(r_buf));
fp = fopen("hello.txt","w+");//w不行,为只写没有读功能,清空
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("打开文件成功\n");
fputs(w_buf,fp);//写入
rewind(fp);
fgets(r_buf,12,fp);//读取
printf("r_buf:%s\n",r_buf);//打印读取到的内容
fclose(fp);
return 0;
}
运行结果:
块读块写:
fread
原型
size_t fread(void *ptr, size_t size, size_t nmemb, FILE fp);
头文件
#include <stdio.h>
功能
读文件
参数
ptr: 要读入的缓冲区指针, 提前申请好的
size: 要读出的信息单元的大小 一般情况下, size设为1
nmemb:要读出的信息单元的个数, size nmemb不大于ptr大小
fp: 要读的文件指针, 提前用fopen打开的
返回值
成功:读取的信息单元的个数
失败: EOF
一般情况下, size设为1, nmemb设为想要读取
的字节数或者ptr指向buf 的大小,返回值为实际读
写的字节数。
fwrite
原型
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE fp);
头文件
#include <stdio.h>
功能
写文件
参数
ptr: 要写入的缓冲区指针, 提前申请好的
size: 要写入的信息单元的大小 一般情况下, size设为1
nmemb:要写入的信息单元的个数, size nmemb不大于ptr大小
fp: 要写的文件指针, 提前用fopen打开的
返回值
成功:写入的信息单元的个数
失败: EOF
一般情况下, size设为1, nmemb设为想要读取
的字节数或者ptr指向buf 的大小,返回值为实际读
写的字节数。
代码演示:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
int w=0,r=0;
char w_buf[12] = "hello world";
char r_buf[12];
memset(r_buf,0,sizeof(r_buf));
fp = fopen("hello.txt","w+");//采样w+,可读写
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("打开文件成功\n");
w = fwrite(w_buf,1,sizeof(w_buf),fp);//返回写入的个数
if(w < 12)
{
perror("fwrite");//为啥失败了
return -1;
}
printf("w = %d\n",w);
rewind(fp);//移动光标
r = fread(r_buf,1,sizeof(r_buf),fp);//返回读取个数
if(r < 12)
{
perror("fread");
return -1;
}
printf("r_buf:%s\n",r_buf);
printf("r = %d\n",r);
fclose(fp);
return 0;
}
运行结果:
格式化读写:
fscanf(格式化输入)
int fscanf ( FILE * fp, const char * format, … );
fscanf从fp中格式化输入
示例
fscanf(fd,"%s",buf);将fd所指向的文件里边的内容输入到buf中
fscanf(fp,"%d %s",&c,d);从fp所指向的文件里边读取一个整数给c,在读取一个字符串给d
fprintf(格式化输出)
int fprintf(FILE *fp, const char *format, …)
fprintf格式化得到的字符串写到fp指向的文件里面
示例 fprintf(fd,"%s","what are you doing ");
sprintf(格式化字符串复制)
int sprintf(char str, const charformat, …)
把某一种类型的数据转换成字符串存放到某一个地址内
#include<stdio.h>
main()
{
char * a=”This is string A!”;
char buf[80];
sprintf(buf,” %s\n”,a);
printf(“%s”.buf);
}
代码演示:
#include <stdio.h>
#include <string.h>
int main()
{
int a = 10, b = 20;
int c,d;
char buff[12];
char buf[12]="helloworld";//空格会有影响
FILE *fp = NULL;
fp = fopen("hello.txt","w+");
if(fp == NULL)
{
perror("fopen");
return -1;
}
fprintf(fp,"%d %d %s",a,b,buf);//以某种个数将内容写入指定文件
rewind(fp);//移动光标
fscanf(fp,"%d %d %s",&c,&d,buff);//读取
printf("c = %d d = %d buff = %s\n",c,d,buff);//打印读取内容
fclose(fp);
return 0;
}
运行结果:
文件指针定位:
API
rewind:
void rewind(FILE *fp);
将读写指针定位到文件开始位置,无返回值
fseek:将读写指针定位到指定位置
fp:要操作的文件
offset:偏移量(可正可负)
whence:参考位置
SEEK_SET //文件开始
SEEK_CUR //文件当前位置
SEEK_END //文件尾
ftell
long ftell(FILE *fp);
返回当前文件读写指针的位置,常用来求文件的大小
作用
操作定位内部的读写指针
代码演示:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
int w=0,r=0;
char w_buf[12] = "hello world";
char r_buf[12];
memset(r_buf,0,sizeof(r_buf));
fp = fopen("hello.txt","w+");
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("打开文件成功\n");
w = fwrite(w_buf,1,sizeof(w_buf),fp);
if(w < 12)
{
perror("fwrite");
return -1;
}
printf("w = %d\n",w);
//fseek(fp,0,SEEK_SET);
fseek(fp,-12,SEEK_CUR);//移动光标
r = fread(r_buf,1,sizeof(r_buf),fp);
if(r < 12)
{
perror("fread");
return -1;
}
printf("r_buf:%s\n",r_buf);
printf("r = %d\n",r);
fclose(fp);
return 0;
}
运行结果:
2.文件I/O(缓冲区文件操作)
接口
(posix接口文件操作)
系统调用接口
中间没有经过缓冲区
实时性高
非常安全和快
打开关闭:
open
原型
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
头文件:
(man 2 open)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
参数
pathname : 要打开文件的路径(相对路径、绝对路径)
flag:(动作标志)
O_RDONLY 读
O_WRONLY 写
O_RDWR 读写
O_CREAT 没有就创建 有就访问
O_EXCL 和O_CREAT连用如果有返回错误
O_TRUNC 将文件截取为0(如果有内容就清空里边的内容)
O_APPEND 追加的方式打开
mode(权限)
当第二个参数有O_CREAT,表示创建文件的时候给定文件的权限
返回值
成功:
返回:文件描述符
失败: -1
close
原型:void close(int fd);
功能:关闭一个打开的文件
头文件
#include <unistd.h>
演示代码:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
int fd;
if(argc < 2)
{
printf("请输入正确的参数\n");
return -1;
}
fd = open(argv[1],O_RDWR|O_CREAT,0666);
if(fd < 0)
{
perror("open");
return -1;
}
printf("打开文件成功\n");
close(fd);
return 0;
}
运行结果:
读写操作:
read
原型
ssize_t read(int fd, void *buf, size_t count);
头文件
#include <unistd.h>
功能
读文件内容到buf
参数
fd
要读文件的路径(相对路径、绝对路径)
buf
要读入的缓冲区, 提前申请好的
count
要读入的字节数
返回值
成功:
返回:实际读的字节数
失败: -1
wirte
原型
ssize_t write(int fd, const void *buf, size_t count);
功能:将buf内容写入文件。
头文件: #include <unistd.h>
参数
fd:打开成功的文件描述符
buf:要写入的数据 提前申请好的
count:写入的数量
返回值
成功:
返回:实际读写的字节数
失败: -1
演示代码:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
int fd;
int r=0,w=0;
char w_buf[12]="hello world";
char r_buf[12];
if(argc < 2)
{
printf("请输入正确的参数\n");
return -1;
}
fd = open(argv[1],O_RDWR|O_CREAT,0666);
if(fd < 0)
{
perror("open");
return -1;
}
printf("打开文件成功\n");
bzero(r_buf,sizeof(r_buf));
w = write(fd,w_buf,12);
if(w != 12)
{
printf("write error\n");
return -1;
}
printf("写成功\n w = %d\n",w);
close(fd);
fd = open(argv[1],O_RDWR|O_CREAT,0666);
f(fd < 0)
{
perror("open");
return -1;
}
printf("打开文件成功\n");
r = read(fd,r_buf,12);
if(r != 12)
{
printf("read error\n");
return -1;
}
printf("read成功\n r = %d\n",r);
printf("r_buf:%s\n",r_buf);
close(fd);
return 0;
}
运行结果:
指针定位(lseek):
原型
off_t lseek(int fd, off_t offset, int whence);
功能
调整或得到文件当前读写的位置
头文件
头文件:
#include <unistd.h>
#include <sys/types.h>
参数
fp 用open打开的文件描述符
offset:想要调整的文件读写位置的相对偏移 负数向左移动 正数向右移动
whence:
调整文件读写位置的基准。
SEEK_SET:当前位置为文件的开头
SEEK_CUR:当前位置为文件指针的位置
SEEK_END:当前位置为文件的结尾
演示代码:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
int fd;
int r=0,w=0;
char w_buf[12]="hello world";
char r_buf[12];
if(argc < 2)
{
printf("请输入正确的参数\n");
return -1;
}
fd = open(argv[1],O_RDWR|O_CREAT,0666);
if(fd < 0)
{
perror("open");
return -1;
}
printf("打开文件成功\n");
bzero(r_buf,sizeof(r_buf));
w = write(fd,w_buf,12);
if(w != 12)
{
printf("write error\n");
return -1;
}
printf("写成功\n w = %d\n",w);
lseek(fd,0,SEEK_SET);
//lseek(fd,-12,SEEK_CUR);
//lseek(fd,-12,SEEK_END);
r = read(fd,r_buf,12);
if(r != 12)
{
printf("read error\n");
return -1;
}
printf("read成功\n r = %d\n",r);
printf("r_buf:%s\n",r_buf);
close(fd);
return 0;
}
运行结果:
参考结构流程图:
文件操作
注:需要使用xmind软件进行查看