C语言文件
文件基础知识
对象
- 对于操作系统而言,所有东西即是文件。
文件分类
- 文件分为数据文件、程序文件。
- 数据文件文件分为:ACSII文件(文本文件)、二进制文件。文本文件:以ACSII字符作为单个数据内容。
- 数据在内存中以二进制储存,不加转化储存到外村(磁盘)则是内存文件的映像文件。文本文件进行了转化。
- 系统定义好了一个文件结构体FILE类型,一般用来定义文件指针,来访问文件,系统根据文件,自动写入相关的信息。注意:文件指针指向的是内存区域文件信息(FILE结构体的第一个元素)的开头地址。
文件的打开和关闭函数
- 打开文件:指的是为文件建立信息区(存放文件的信息)和文件缓冲区(存储暂时输入输出的数据)
- 打开文件函数 FILE *fopen("filename","r、r+、rb、w+")
- "filename"=字符数组指针 or文件path ,同一目录下不用加path。
#include <stdio.h>
#include <cstdlib>
int main()
{
FILE *fp;
if(fopen("1.txt","rb")==NULL)
{
printf("error");
exit(0);
}//判断是否是空指针
//内存大小不够会导致w文件错误,返回空指针
//
printf("%d",16|1);
return 0;
}
- 关闭文件:撤销文件信息区域,和文件缓存区域
- 关闭文件函数FILE *fclose(fp) fp为文件指针。
- 如果不关闭文件,且文件缓冲区没有满,在这时结束程序会导致文件数据丢失。所以要先关闭文件。
顺序读写文件数据
- 注意:计算机输入ASCII字符时候,遇到回车换行符号时,输出到终端转化为回车、换行两个符号。以二进制输入不会。
相关函数
- 从指定文件读入单个字符函数fgetc、读入字符串函数fgets
```int fgetc(
FILE *stream
);//成功返回1,否则返回EOF。文件指针可以是stdin
wint_t fgetwc(
FILE *stream
);
char * fgets ( char * str, int num, FILE * stream );//需要提前定义一个字符数组。
- 输出单个字符到指定文件函数fputc、输出字符串到指定文件函数fputs
int fputc ( char c, FILE * stream );
int fputs (string c | char * c, FILE *stream)
也就是可以是字符常量、字符串常量,或者就是相应的指针。
实例
操作实例1:
#include <stdio.h>
#include <cstdlib>
#include <unistd.h>
int main() {
FILE *fp;
char ch;
char name[10];
#ifdef debug
scanf("%s", name);
#endif
if ((fp = fopen("t1.txt", "r")) == NULL) {
fprintf(stderr, "error");
exit(0);
}
// ch = getchar();//接受最后输入得回车符
// ch = getchar();
#ifdef debug
while (ch != '#') {
fputc(ch, fp);
//将一个字符输出到子盘文件上,如果输出失败,则返回EOF,值为-1.
ch = getchar();
}
fclose(fp);//关闭文件
#endif
char name1[10];
FILE *fp1;
scanf("%s",name1);
if((fp1=fopen(name1,"w"))==NULL)
{
fprintf(stderr,"error");
exit(EXIT_SUCCESS);
}
ch=getchar();
while(!feof(fp))
{
// ifeof(fp)遇到文件结束标识符就返回0,否则返回一个不同于0的值;随着文件读写位置标记来进 行识别
// int feof ( File * Stream );
fputc(fgetc(fp),fp1);
//从指定的文件按照顺序读入一个字符。
putchar(fgetc(fp));
}
fclose(fp1);
fclose(fp);
return 0;
}
操作实例2:
#include <stdio.h>
#include <cstdlib>
#include <unistd.h>
int main() {
FILE *fp;
char ch;
char name[10];
#ifdef debug
scanf("%s", name);
#endif
if ((fp = fopen("t1.txt", "r")) == NULL) {
fprintf(stderr, "error");
exit(0);
}
// ch = getchar();//接受最后输入得回车符
// ch = getchar();
#ifdef debug
while (ch != '#') {
fputc(ch, fp);
//将一个字符输出到子盘文件上,如果输出失败,则返回EOF,值为-1。
ch = getchar();
}
fclose(fp);//关闭文件
#endif
char name1[10];
FILE *fp1;
scanf("%s",name1);
if((fp1=fopen(name1,"w"))==NULL)
{
fprintf(stderr,"error");
exit(EXIT_SUCCESS);
}
ch=getchar();
char str[15];
fputs(fgets(str,4,fp),fp1);
//全部读入只需要把4给的很大
fclose(fp1);
fclose(fp);
return 0;
}
操作实例3:
/* fputs example */
#include <stdio.h>
int main ()
{
FILE * pFile;
char sentence [256];
printf ("Enter sentence to append: ");
fgets (sentence,256,stdin);
pFile = fopen ("mylog.txt","a");
//若是以r打开文件则不能读入从终端输入的字符,stdin标准输入流
fputs (sentence,pFile);
fclose (pFile);
return 0;
}
用格式化等的方式读写文件
int fprintf ( FILE * stream, const char * format, ... );
fprintf(fp,"%d,%s,%f",12,"asd",12.963);
//将这些输出列表元输出到文件
int fscanf ( FILE * stream, const char * format, ... );
将fp对应文件的两个整型值赋给i,j。
fscanf(fp,"%d ,%d,",&i,&j)
//缺点:由于fscanf要先从文件读入ASCII码数据时,要先在内存中进行转化二进制,然后才能保存到对饮的内存变量之中,所以耗时较大;
//fprintf在输出ASCII码数据到文件时,同样要先在内存中间转化为二进制数据,故耗时也很大。
操作实例
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp;
if ((fp = fopen("t1.txt", "w+")) == NULL) {
printf("d");
}
struct stu
{
int id;
char name[];
}en;
fprintf(fp,"%d,%s",56,"sdji");
fscanf(fp,"%d,%s",&en.id,en.name);
printf("%d",en.id);
return 0;
}
用二进制方式向文件读写一组数据
- 读写的时候是以二进制形式进行的,故fopen打开文件要以"rb,wb,rb+,wb+"
- fread 函数
//函数格式
size_int fread ( void * ptr, size_t size, size_t count, FILE * stream );
//ptr表示从文件读入的数据 的起始储存地址(存到哪里去)。
//函数为int整型函数,成功读入返回值为cout的值,即为读入数据项的个数。size读写的单个数据占多少个字节,cout表示读写多少个字节为size的数据。
- fwrite函数
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
//ptr要输入文件的数据的初始地址(哪里的数据要向文件输入)。其他同上。
- 操作实例
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define SIZE 3
#define debug
int main() {
typedef struct student {
int id;
char name[10];
} stu;
stu s[SIZE];
for (int i = 0; i < SIZE; i++) {
scanf("%d%s", &s[i].id, s[i].name);
}
FILE *fp;
if ((fp = fopen("t1.txt", "rb+")) == NULL) {
fprintf(stderr, "err");
exit(0);
}
for (int i = 0; i < SIZE; i++) {
if (fwrite(&s[i], sizeof(stu), 1, fp) != 1)
printf("d\n");
}
fclose(fp);
FILE *fp1;
fp1 = fopen("t1.txt", "rb+");
stu ren[3];
#ifdef debug
for (int i = 0; i < SIZE; i++) {
fread(&ren[i], sizeof(stu), 1, fp1);
printf("%d %s\n", ren[i].id, ren[i].name);
}
fclose(fp1);
#endif
return 0;
}
二进制输出、读入数据注意事项
- //向文件输出那种类型数据,则读出数据的时候也应该定义相应类型的变量来接入
- fwrit文件(将数据写入文件以后)以后一定要先关闭文件,然后才用fread读入文件里面的数据。对于一个空白文件来说,写入数据以后文件读写标记移动到文件末尾(文件结束标志),此时将文件的数据读出,则是从文件末尾读出,但是后面是空白,所以会出现错误。
随机读写文件数据
- rewind函数
//void rewind ( FILE * stream );
//函数将文件的读写表示符移动到文件初始位置。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define SIZE 3
#define debug
int main() {
typedef struct student {
int id;
char name[10];
} stu;
stu s[SIZE];
for (int i = 0; i < SIZE; i++) {
scanf("%d%s", &s[i].id, s[i].name);
}
FILE *fp;
if ((fp = fopen("t1.txt", "rb+")) == NULL) {
fprintf(stderr, "err");
exit(0);
}
for (int i = 0; i < SIZE; i++) {
if (fwrite(&s[i], sizeof(stu), 1, fp) != 1)
printf("d\n");
}
rewind(fp);
stu ren[3];
#ifdef debug
for (int i = 0; i < SIZE; i++) {
fread(&ren[i], sizeof(stu), 1, fp);
printf("%d %s\n", ren[i].id, ren[i].name);
}
fclose(fp);
#endif
return 0;
}
- fseek函数
int fseek ( FILE * stream, long int offset, int origin );
//origin 的值为0,1,2;其中0表示文件开头的位置,1表示文件表示符当前的位置,2表示文件末尾行。
//offset表示标识符移动的单位距离,值为正表示向前移动看,值为负表示向后移动。
//前面是定义了一个包含了两个元素的结构体,并且读入了三个结构体变量数据给fp指向的文件
rewind(fp);
stu ren[3];
fseek(fp,sizeof(stu),1);
#ifdef debug
if(fread(&ren[1].id,4,1,fp)!=1)
printf("%s","cao");
printf("%d",ren[1].id);
fclose(fp);
#endif
return 0;
- ferror、clearerr函数
int ferror ( FILE * stream );
//当读取文件数据,或者写入数据到文件没有问题的时候函数值返回为0;否则返回一个非零值。
注意:对于同一文件而言每次读取操作都会产生一个ferror函数值,应该及时检验
void clearerr ( FILE * stream );
清除ferror的函数值,避免上一步读写操作的ferror值影响到下一次读写是否错误的判断。
fscanf,fprintf,fread,fwrite函数返回值
- 这四个函数成功执行返回写入文件\从文件读出 的数据个数,否则返回EOF。
- fputc、fputs成功执行返回0,否则返回EOF
- fgetc成功执行返回字符首地址,否则返回NULL 、fgets成功执行返回数组首地址,否则返回NULL