Linux标准I/O
文件打开/关闭
fopen函数
用于文件的输入输出
接口代码
#include<stdio.h>
FILE* fopen(const char* filename,const char* mode)
参数解释
filename
: 文件名称mode
: 打开模式r
: 以只读方式打开w
: 以写方式打开,将文件长度清0a
: 以写方式打开,追加在文件尾r+
: 以修改方式打开(读和写)w+
: 以修改方式打开,将文件长度清0a+
: 以修改方式打开,新内容追加在文件尾
代码实例
#include<stdio.h>
int main()
{
FILE *fp;
fp = fopen("a.txt", "r");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;//返回错误码
}
return 0;
}
fclose函数
关闭指定文件流stream,使所有尚未写出的数据都写出
接口代码
#include<stdio.h>
int fclose(FILE* stream)
参数解释
stream
: 要关闭文件的文件指针
代码实例
#include<stdio.h>
int main()
{
FILE *fp;
fp = fopen("a.txt", "r");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;//返回错误码
}
fclose(fp);
return 0;
}
文件读写
fread函数
从一个文件流中 读取数据.数据文件从文件流stream读到ptr指定的数据缓冲区里,函数返回值是成功读到数据缓冲区里的记录个数(不是字节数)
接口代码
#include<stdio.h>
size_t fread(void* ptr,size_t size,size_t nitems,FILE* stream)
参数解释
ptr
: 数据缓冲区,多为字符串size
: 每个数据记录的长度nitems
: 需要传输的记录个数
代码实例
#include<stdio.h>
int main()
{
FILE *fp;
fp = fopen("a.txt", "r");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;//返回错误码
}
char str[1024] = {0};//sizeof()求长度
//char str[] = "1123344";strlen()求长度
fread(str, sizeof(char), sizeof(str), fp);
printf("%s", str);
return 0;
}
注意事项
fread函数
每次会将缓冲区数据覆盖写入- 使用
fread函数
需要定义缓冲区大小 - 按照上方定义的
str
必须使用sizeof()
,而不能使用strlen()
,因为后者读取的长度是以\0
结尾的长度
fwrite函数
从指定的缓冲区里读取数据记录,并把他们写到输出流中,返回值为成功写入的记录个数
接口代码
#include<stdio.h>
size_t fwrite(const void* ptr,size_t size,size_t nitems,FILE* stream)
参数解释
ptr
: 缓冲区size
: 每个数据记录的长度nitems
: 需要传输的记录个数stream
: 输出流文件
代码实例
#include<stdio.h>
int main()
{
FILE *fp;
fp = fopen("a.txt", "r");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;//返回错误码
}
char str[] = "this is test try";
fwrite(str, sizeof(char), strlen(str),fp);
return 0;
}
注意事项
- 当缓冲区设置过大时,就会将缓冲区内的所有文件都读入到
fp
中,包括空格字符 - 当程序运行结束时,系统会自动将缓冲区内容写入到
fp
中
fflush函数
将文件流里所有未写出的数据立刻写出
什么情况下写出数据?
- 缓冲区满
- 程序结束
- 遇到
\n
- 刷新函数
fflush()
接口代码
#include<stdio.h>
int fflush(FILE* stream)
参数解释
stream
: 要写入数据的目标文件
代码实例
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <io.h>
void flush(FILE *stream);
int main() {
FILE *fp;
char msg[] = "This is a test";
fp = fopen("test.txt", "a+");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;
}
fwrite(msg, strlen(msg), 1, fp);
printf("Press ant key to flush fp");
getch();
flush(fp);
printf("\nPress ant key to quit");
getch();
return 0;
}
void flush(FILE *stream) {
int duphandle;
fflush(stream);
// 获取 stream函数的文件描述符
duphandle = dup(fileno(stream));
// 通过文件描述符关闭文件
close(duphandle);
}
fgetc/getc/getchar函数
上述函数都是从文件流里读取下一个字节并把它作为一个字符返回.当到达文件尾时,返回EOF
接口代码
#include<stdio.h>
int fgetc(FILE* stream);
int getc(FILE* stream);
int getchar();
参数解释
stream
: 读取数据的目标文件
实例代码
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;
}
char str[1024] = {0};
int cnt = fgetc(fp);
while (cnt != EOF) {
cnt = fgetc(fp);
}
fclose(fp);
return 0;
}
注意事项
- 本函数接口采用单字节读入,所以读完一个文件的数据必须要使用循环读入
fputc/putc/putchar函数
与上述单字节读对应,这三个函数为单字节写函数.把一个字符写到一个输出文件流中.返回写入的值,如果失败返回EOF
接口代码
#include<stdio.h>
int fputc(int c,FILE* stream);
int putc(int c,FILE* stream);
int putchar(int c);
参数解释
stream
: 写入到目标文件中
实例代码
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen("fread函数.cpp", "a+");
FILE *fq;
fq = fopen("test.txt", "a");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;
}
if (fq == NULL) {
printf("目标文件不存在\n");
fclose(fp);
return -1;
}
int cnt = fgetc(fp);
while (cnt != EOF) {
fputc(cnt, fq);
cnt = fgetc(fp);
}
fclose(fp);
fclose(fq);
return 0;
}
fgets/gets
从参数
fp
指向的文件流中提取一行数据,并写入到str
为首地址的内存中,函数返回str
的原值文件流达到结尾,fgets
返回NULL
接口代码
#include<stdio.h>
char* fgets(char* str,int size,FILE* fp);
参数解释
str
: 存储从fp
中读出的数据size
: 一行的长度fp
: 源文件
实例代码
//参考fputs/puts
注意事项
- 当提取一行数据时,提取过程可能因为遇到换行符或文件末尾结束,也可能提取
size-1
个字符后结束.但不论怎样结束,fgets
都会在每行数据最后添加\0
,表示字符串结束
fputs/puts
与上述行读入对应,这两个函数为行写入
接口代码
#include<stdio.h>
int fputs(const char* str,FILE* fp);
参数解释
str
: 要写入目标文件的字符串fp
: 目标文件
实例代码
#include <stdio.h>
#define size (1000+1)
int main() {
FILE *fp;
fp = fopen("fread函数.cpp", "a+");
FILE *fq;
fq = fopen("test.txt", "a");
if (fp == NULL) {
printf("源文件不存在\n");
return -1;
}
if (fq == NULL) {
printf("目标文件不存在\n");
fclose(fp);
return -1;
}
char buf[size-1];
while (fgets(buf,size-1,fp))fputs(buf,fq);
fclose(fp);
fclose(fq);
return 0;
}
freopen函数
把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件
直接就把各种输出重定向到stream流
接口代码
#include<stdio.h>
FILE *freopen(const char *pathname, const char *type, FILE *fp);
参数解释
filename
: 包含了要打开的文件名称mode
: 文件访问模式,与上面类似stream
: 源文件对象指针
实例代码
#include <stdio.h>
int main() {
FILE *fp;
printf("该文本重定向到 stdout\n");
fp = freopen("file.in", "w+", stdout);
printf("该文本重定向到 file.txt\n");
fclose(fp);
return (0);
}
fdopen函数
将文件描述符转为文件流
将流与文件句柄连接
接口代码
#include<stdio.h>
FILE *fdopen(int fildes, const char *type);
参数解释
fileds
: 是一个有效的文件描述符type
: 是一个指向字符串的指针,指定了流的打开模式
实例代码
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
//open系统打开函数
int fd = open("example.txt", O_RDWR);
if (fd == -1) {
perror("open");
return 1;
}
FILE *stream = fdopen(fd, "r+");
if (stream == NULL) {
perror("fdopen");
close(fd);
return 1;
}
// 现在可以使用stream这个FILE指针进行读写操作
printf("%s\n", fgets(stream, 100, stream));
// 关闭文件描述符和流
fclose(stream);
close(fd);
return 0;
}
输入输出处理
printf/fprintf/sprintf
三种输出函数,能够对各种不同类型的参数进行格式编排和输出
接口代码
#include<stdio.h>
int printf(const char* format,...);
//format: 每个参数在输出流中的表示形式
int sprintf(char* s,const char* format,...);
//s: 将输出结果保存到s中
//format: 每个参数在输出流中的表示形式
int fprintf(FILE* stream,const char* format,...);
//stream: 将输出结果保存到文件中
//format: 每个参数在输出流中的表示形式
参数解释
参考上面
实例代码
#include <stdio.h>
int main() {
FILE *fq;
fq = fopen("test.txt", "a");
if (fq == NULL) {
printf("目标文件不存在\n");
return -1;
}
fprintf(fq, "Are you OK!Haha");
fclose(fq);
char str[20];
sprintf(str, "laokekeke");
printf("%s", str);
return 0;
}
scanf/sscanf/fscanf函数
与输出函数类似,这是对应的输出函数
接口代码
#include<stdio.h>
int scanf(const char* format,...);
//format: 每个参数在输入流中的表示形式
int sscanf(const char* s,const char* format,...);
//s: 从s中获得输入
//format: 每个参数在输入流中的表示形式
int fscanf(FILE* stream,const char* format,...);
//stream: 从stream文件中获得输入
//format: 每个参数在输入流中的表示形式
参数解释
参考上方
实例代码
#include <stdio.h>
int main() {
FILE *fq;
fq = fopen("test.txt", "r");
if (fq == NULL) {
printf("目标文件不存在\n");
return -1;
}
char str1[10] = {0}, str2[10] = {0}, str3[10] = {0};
fscanf(fq, "%s %s %s", str1, str2, str3);
printf("%s %s %s\n", str1, str2, str3);
fclose(fq);
char mode[] = "Are you ok";
sscanf(mode, "%s %s %s", str1, str2, str3);
printf("%s %s %s", str1, str2, str3);
return 0;
}
remove函数
相当于
unlike
函数,但如果它的path参数是一个目录的话,作用相当于rmdir函数
接口代码
#include<stdio.h>
int remove(char* filename);
参数解释
filename
: 要删除的文件名称/目录
实例代码
#include <stdio.h>
int main() {
char file[80];
printf("File to delete: ");
gets(file);
if (remove(file) == 0)printf("Removed %s.\n", file);
else perror("remove");
return 0;
}
文件指针读取,修改
fgetpos/fsetpos函数
fgetpos
: 获取流 stream 的当前文件位置,并把它写入到pos
fsetpos
: 设置给定流 stream 的文件位置为给定的位置.参数 pos 是由函数fgetpos
给定的位置。
返回值
: 成功返回 0
接口代码
#include<stdio.h>
int fgetpos(FILE* fp,fpos_t* pos);
//fp: 指向源文件的指针
//pos: 指向fpos_t的指针
int fsetpos(FILE* fp,const fpos_t* pos);
//fp: 指向源文件的指针
//pos: 指向fpos_t对象的指针,该对象包含了之前通过fgetpos获得的位置
参数解释
参考上方
实例代码
#include <stdio.h>
int main() {
FILE *fp;
fpos_t position;
fp = fopen("test.txt", "a");
if (fp == NULL) {
printf("源文件无法打开\n");
return -1;
}
fgetpos(fp, &position);
fputs("Hello, World!", fp);
//修改指针位置
position += position;
fsetpos(fp, &position);
fputs("这将覆盖之前的内容", fp);
fclose(fp);
return 0;
}
注意事项
- 这个函数只能读取文件指针,修改指针要考
fseek
函数
fseek函数
与
lseek
系统调用等价的文件流函数.它在文件流里为下一次读写操作指定位置,但函数返回值是一个整数,表示成功与否
接口代码
#include<stdio.h>
int fseek(FILE* stream,long int offset,int whence)
参数解释
stream
: 修改指针的源文件offset
: 偏移量,右偏为正,左偏为负whence
: 起始位置SEEK_SET 0
: 文件头SEEK_CUR 1
: 当前位置SEEK_END 2
: 文件尾
实例代码
#include <stdio.h>
#include <string.h>
int main() {
FILE *stream;
char msg[] = "this is a test ko";
char buf[20];
stream = fopen("test.txt", "w+");
if (stream == NULL) {
printf("源文件打开失败\n");
return -1;
}
fwrite(msg, strlen(msg) + 1, 1, stream);
// 修改指针位置
fseek(stream, 2, SEEK_SET);
fread(buf, 1, strlen(msg) + 1, stream);
printf("%s\n", buf);
fclose(stream);
return 0;
}
注意事项
fseek函数
修改的只是当前系统在该文件中的指针
ftell函数
ftell
: 返回文件流当前(读写)位置
接口代码
#include<stdio.h>
long ftell(FILE* fp);
参数解释
fp
: 要操作源文件的指针
实例代码
#include <stdio.h>
int main() {
FILE *fp;
int len;
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("打开文件错误");
return (-1);
}
fseek(fp, -10, SEEK_END);
len = ftell(fp);
fclose(fp);
printf("test.txt文件的指针 = %d 字节\n", len);
return (0);
}
rewind函数
rewind
: 重置文件流的读写位置
接口代码
#include<stdio.h>
void rewind(FILE* fp);
参数解释
fp
: 要操作源文件的指针
实例代码
#include <stdio.h>
int main() {
FILE *fp;
int len;
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("打开文件错误");
return (-1);
}
fseek(fp, -10, SEEK_END);
len = ftell(fp);
printf("重置前文件的指针 = %d 字节\n", len);
rewind(fp);
len = ftell(fp);
printf("重置后文件的指针 = %d 字节\n", len);
fclose(fp);
return (0);
}
缓冲区
目前来看,暂时用处不大
setbuf函数
设置文件流的缓冲区
接口代码
#include<stdio.h>
void setbuf(FILE* fp,char* buf);
参数解释
fp
: 源文件对象的指针buffer
: 分配给用户的缓冲,它的长度至少为BUFSIZ字节,BUFSIZ 是一个宏常量,表示数组的长度
实例代码
#include <stdio.h>
int main() {
char buf[BUFSIZ];
setbuf(stdout, buf);
puts("This is runoob");
printf("%llu", sizeof(buf));
fflush(stdout);
return 0;
}
注意事项
stdout
: 默认为行缓冲,再设置缓冲区后,缓冲区就不为行缓冲,需要强制刷新
setvbuf函数
设置文件流的缓冲机制
返回值
: 成功返回0
接口代码
#include<stdio.h>
void setvbuf(FILE* fp,char* buf,int mode,size_t size);
参数解释
-
fp
: 源文件对象的指针 -
buf
: 这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲 -
mode
: 文件缓冲模式_IOFBF
: 全缓冲IOLBF
: 行缓冲IONBF
: 无缓冲
size
: 缓冲大小,以字节为单位
实例代码
#include <stdio.h>
int main() {
FILE *input, *output;
char buf[512];
input = fopen("file.in", "r+b");
output = fopen("file.out", "w");
if (setvbuf(input, buf, _IOFBF, 512) != 0)
printf("failed to set up buffer for input file\n");
else printf("buffer set up for input file\n");
if (setvbuf(output, NULL, _IOLBF, 132) != 0)
printf("failed to set up buffer for output file\n");
else printf("buffer set up for output file\n");
fclose(input);
fclose(output);
return 0;
}