读写函数接口
1、fgetc
语法:
功能:从流中获取一个字符
练习1:编写程序统计文件的行数
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
char ch = 0;
int row = 0;
fp = fopen("file.txt","r");
if (NULL == fp)
{
perror("file to fopen!");
return -1;
}
while(1)
{
ch = fgetc(fp);
if (EOF == ch)
{
break;
}
if (ch == '\n')
{
++row;
}
}
printf("row = %d\n",row);
return 0;
}
2、fgetc/fputc 与 getchar( ) / putchar( )的区别
fgetc 和 fputc 操作ASCII码文件单个字符
char ch = 0;
ch = getchar( ); == ch = fgetc(stdin); // 等价关系
ch = putchar( ): == ch = fputc(stdout); // 等价关系
练习2:将源文件的内容写到目的文件中
#include <stdio.h>
int main(void)
{
FILE *fp1 = NULL;
FILE *fp2 = NULL;
char ch = 0;
fp1 = fopen("dest.txt","w");
fp2 = fopen("src.txt","r");
if (NULL == fp1 || NULL == fp2)
{
perror("fail to fopen!");
return -1;
}
while (1)
{
ch = fgetc(fp2);
if (EOF == ch)
{
break;
}
fputc(ch,fp1);
}
fclose(fp1);
fclose(fp2);
return 0;
}
3、fputs
int fputs(const char *s, FILE *stream); // stream文件流指针
功能:把字符串写入流中,不会写字符串的 ' \0 '
返回值:成功返回非负数、失败返回EOF
例:
#include <stdio.h>
int main(void)
{
char s[32] = "hello";
FILE *fp = NULL;
fp = fopen("fputs.txt","w");
if (fp == NULL)
{
perror("fail to fopen");
return -1;
}
fputs(s,fp);
fclose(fp);
return 0;
}
4、fgets
char *fgets(char *s, int size, FILE *stream);
功能:从流中读取一个字符串(最多读4095个—要保留一位给\0)
参数:s—存放字符串空间首地址;size—最多读取个数;stream—文件流指针
返回值:成功返回存放字符串空间的首地址;失败返回NULL;读到文件末尾也会返回NULL
5、fputs/ fgets与gets / puts 的区别
1)gets没有给定最多读取字符的个数,有越界风险
fgets需要给定最多读取的字符个数,没有越界的风险
2)gets会去掉从终端接收的/n,换成/0
fgets则会保留并在末尾加上/0
3)puts会在字符串末尾多打印一个/n字符
fputs不会在末尾多打印/n字符
6、fwrite(二进制)
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:向流中写入nmemb个对象,每个对象size字节大小,在ptr指向的空间中
参数:ptr:要写入的内容所在的空间的首地址
size:写入每个数据的大小
nmemb:数据的个数
stream:文件流指针
返回值:成功返回写入对象的个数,失败返回0,读到文件末尾返回0
#include <stdio.h>
typedef struct Stu
{
char name[32];
char sex;
int age;
int score;
}stu;
int main(void)
{
stu a = {"zhangsan",'m',19,100};
stu s[3] = {{"aa",'m',18,90},{"bb",'f',18,90},{"cc",'f',20.99}};
FILE *fp = NULL;
fp = fopen("fwrite.txt","w");
if (NULL == fp)
{
perror("fail to fopen!");
return -1;
}
fwrite(&a,sizeof(stu),1,fp);
fwrite(s,sizeof(stu),3,fp);
fclose(fp);
return 0;
}
7、fread(二进制)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从流中读取nmemb个对象,每个对象size个字节,存放到ptr指向的空间中
参数:ptr:要读的内容所在的空间的首地址
size:读的内容每个数据的大小
nmemb:数据的个数
stream:文件流指针
返回值:成功返回读到对象的个数,失败返回0,读到文件末尾返回0
练习3:利用fread和fwrite完成将src.jpg图片内容拷贝到dst.jpg图片中
#include<stdio.h>
int main(void)
{
FILE *fp1 = NULL;
FILE *fp2 = NULL;
size_t ret
char s[4096] = {0};
fp1 = fopen("des.jpg","w");
fp2 = fopen("src.jpg","r");
if (fp1 == NULL || fp2 == NULL)
{
perror("fail to fopen!");
return -1;
}
while(1)
{
ret = fread(s, 1, sizeof(s), fp2);//每次读一个字节,读s大小次
printf("ret = %ld\n",ret);
if (ret == 0)
{
break;
}
fwrite(s, 1, ret, fp1);//每次写一个字节,写ret次—可以保证最后一次写的也是读的数据个数
}
fclose(fp1);
fclose(fp2);
return 0;
}
8、fscanf
int fscanf(FILE *stream, const char *format, ...);
功能:从流中读取格式化的字符串(读不了带空格的字符串)
9、fprintf
int fprintf(FILE *stream, const char *format, ...);
功能:将格式化字符串输入到指定流中
#include<stdio.h>
int main(void)
{
FILE *fp = NULL;
int Num1 = 100;
int Num2 = 200;
fp = fopen("file.txt","w");
if (fp == NULL)
{
perror("fail to fopen!");
return -1;
}
fprintf(fp,"hello world\nNum1 = %d\nNum2 = %d\n",Num1,Num2);
fclose(fp);
return 0;
}
流的定位
1、ftell
long ftell(FILE *stream);
功能:获得流的偏移量
2、rewind
void rewind(FILE *stream);
功能:将流的偏移量重新设置到开头
3、fseek
int fseek(FILE *stream, long offset, int whence);
功能:设置流的偏移量
参数:
stream:文件流指针
offset:偏移量>0向后便宜 <0向前偏移
whence:
SEEK_SET 文件开头
SEEK_CUR 文件当前位置
SEEK_END 文件末尾
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
fp = fopen("file.txt","w");
if (fp == NULL)
{
perror("fail to fopen");
return -1;
}
fseek(fp, 10, SEEK_SET);
fputc('a',fp);
fseek(fp, -5, SEEK_CUR);
fputc('a',fp);
fseek(fp, 1, SEEK_SET);
fputc('a',fp);
fclose(fp);
return 0;
}
练习4:编写一个程序实现统计一个文件的大小
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
fp = fopen("file.txt","r");
if (fp == NULL)
{
perror("fail to fopen");
return -1;
}
fseek(fp, 0, SEEK_END);
long len = ftell(fp);
printf("len = %ld\n",len);
return 0;
}
练习5:读取bmp图片类型的宽度和高度
注:图片的宽度和高度在图片的信息里
typedef struct tagBITMAPFILEHEADER { // bmfh
WORD bfType; //占2字节
DWORD bfSize; //占4字节
WORD bfReserved1; //占2字节
WORD bfReserved2; //占2字节
DWORD bfOffBits; //占4字节
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{ // bmih
DWORD biSize;
LONG biWidth; //4字节
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
#include <stdio.h>
int main(void)
{
FILE *fp = NULL;
fp = fopen("src.bmp","r");
int width = 0;
int height = 0;
if (fp == NULL)
{
perror("fail to fopen!");
return -1;
}
fseek(fp,18,SEEK_SET);
fread(&width,sizeof(width),1,fp);
fread(&height,sizeof(height),1,fp);
fclose(fp);
printf("width = %d\n",width);
printf("height = %d\n",height);
return 0;
}
练习6:从终端输入一个单词,获得单词的含义
注:dict.txt文件为英文词典文件,如:
abbess n. woman who is head of a convent or nunnery
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[32];
char tmpbuff[4094];
char *ptmp = NULL;
printf("Input a word to search: ");
putchar('\n');
gets(s);
FILE *fp = NULL;
fp = fopen("dict.txt","r");
if (fp == NULL)
{
perror("fail to fopen");
return -1;
}
while (1)
{
char *pret = NULL;
pret = fgets(tmpbuff, sizeof(tmpbuff), fp);//读取文件一行
if (pret != NULL)
{
ptmp = tmpbuff;
while (*ptmp != ' ' && *ptmp != '\0')
{
++ptmp;
}
*ptmp = '\0';
++ptmp;
while (*ptmp == ' ')
{
++ptmp;
}//将一行进行解析,解析为单词和含义两部分
}else
{
printf("No word!\n");
fclose(fp);
return -1;
}
if (strcmp(s,tmpbuff) == 0)
{
printf(" Word: %s\n",s);
printf("Tmpbuff: %s\n",tmpbuff);
printf("Meaning: %s\n",ptmp);
break;
}
}
fclose(fp);
return 0;
}
标准IO重点总结:
文件内容拷贝
fgetc / fputc
fgets / fputs
fread / fwrite