C语言文件操作笔记-1
C文件操作
- 文件函数说明
- 相关函数说明:
- fopen
- fclose
- fgetc
- fgets
- getc
- ungetc
- fputc
- fputs
- fputs
- fputs
- puts
- feof
- 示例代码:
- 示例1:使用fgetc读到文件结束并逐个使用fputc打印
- 示例2:fgets读取文件字符串
- 示例3:getc位置递增演示
- 示例4:fputs测试
- 示例5:getchar与putchar
- 示例6:puts与putc
- 示例7:fgetc
- 示例8:ungetc
- 示例9:r+是追加还是新建?
- 示例10:fgets遇\0结束?
- 示例11:fgets从标准输入流写入时不足设置长度将会读入回车
文件函数说明
此为基础篇文件操作,涉及基础使用函数:
fopen、fclose、fgetc、fgets、getc、fputcs、getchar、putchar、puts、putc、fgetc、ungetc等函数说明。
相关函数说明:
fopen
函数说明: fopen
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:fopen* 函数入口:* pathname:打开文件的绝对路径* mode:文件打开模式* 函数出口:* FILE:返回该文件的指针(句柄),错误打开返回NULL* 函数说明:* 按照指定打开方式打开指定路径的文件 * ***************************/
FILE *fopen(const char *pathname, const char *mode);
以下内容区分大小写!!!
以下内容区分大小写!!!
以下内容区分大小写!!!
参数 | 说明 |
---|---|
r | 只读打开方式,文件必须存在 |
r+ | 读写打开方式,文件必须存在,当文件被写入时会在当前流指针处进行写入,如果当前指针流处有字符将会被覆盖。 |
rb | 只读打开二进制文本,该文件必须存在 |
rb+ | 读写打开二进制文本,该文件必须存在 |
当文件被写入时会在当前流指针处进行写入,如果当前指针流处有字符将会被覆盖。 | |
w | 以新建只写方式打开,文件已存在内容将会被清空 |
w+ | 因新建读写方式打开,文件已存在将会被清空 |
wb | 以新建写二进制文件方式打开,文件已存在将会被清空 |
wb+ | 以新建读写二进制文件方式打开,文件已存在将会被清空 |
a | 以追加或新建文件方式打开,文件只允许在文件末尾追加 |
a+ | 以可读、追加或新建文件方式打开,文件只允许在文件末尾追加 |
ab | 以追加或新建二进制文件方式打开,件只允许在文件末尾追加 |
ab+ | 以可读,追加或新建二进制文件方式打开,件只允许在文件末尾追加 |
fclose
函数说明: fclose
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:fclose* 函数入口:* stream 文件流* * 函数出口:* 如果流成功关闭,则该方法返回零。如果失败,则返回 EOF。* 函数说明:* 关闭流 stream。刷新所有的缓冲区。* ***************************/
int fclose(FILE *stream);
fgetc
函数说明: fgetc
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:fgetc* 函数入口:* stream:文件流* 函数出口:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发
* 读错误,则返回 EOF。* 函数说明: 向指定流中读出一个字符* ***************************/int fgetc(FILE *stream);
fgets
函数说明: fgets
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:fgets* 函数入口:* s:存储读出字符串大小的缓冲区* size:读出大小* stream:文件流* 函数出口:* 如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。* 如果发生错误,返回一个空指针。* 函数说明: 向指定流中读出一个字串放入到变量s中* ***************************/
char *fgets(char *s, int size, FILE *stream);
getc
函数说明: getc
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:getc* 函数入口:stream:文件流* 函数出口:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。* 函数说明:从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符递增移动。* 默认只会执行n-1个字符,默认一个字符会在末尾加上\0* ***************************/
int getc(FILE *stream);
ungetc
函数说明: ungetc
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:ungetc* 函数入口:c:这是要被推入的字符。该字符以其对应的 int 值进行传递。* stream:这是指向 FILE 对象的指针,该 FILE 对象标识了输入流。* 函数出口:如果成功,则返回被推入的字符,否则返回 EOF,且流 stream 保持不变。* 函数说明:把字符 char(一个无符号字符)推入到指定的流 stream 中,以便它是下一个被读取到的字符。* ***************************/
int ungetc(int c, FILE *stream);
fputc
函数说明: fputc
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:fputc* 函数入口:c:这是要被写入的字符。该字符以其对应的 int 值进行传递。* stream: 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。* 函数出口:如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。* 函数说明:把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。* ***************************/
int fputc(int c, FILE *stream);
fputs
函数说明: fputs
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:fputs* 函数入口:str:这是一个数组,包含了要写入的以空字符终止的字符序列。* stream:这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流。* 函数出口:该函数返回一个非负值,如果发生错误则返回 EOF。* 函数说明:把字符串写入到指定的流 stream 中,但不包括空字符。* ***************************/
int fputs(const char *s, FILE *stream);
fputs
函数说明: fputs
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:putc* 函数入口:c:这是要被写入的字符。该字符以其对应的 int 值进行传递。* stream:这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。* 函数出口:该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误则返回 EOF。* 函数说明:把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。不会自动在文件末尾添加\0* ***************************/
int putc(int c, FILE *stream);
fputs
函数说明: fputs
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:ungetc* 函数入口:c:这是要被写入的字符。该字符以其对应的 int 值进行传递。* 函数出口:该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误则返回 EOF。* 函数说明:把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中。* ***************************/
int putchar(int c);
puts
函数说明: puts
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:puts* 函数入口:str:这是要被写入的 C 字符串。* 函数出口:如果成功,该函数返回一个非负值为字符串长度(包括末尾的 \0),如果发生错误则返回 EOF。* 函数说明:把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中。* ***************************/
int puts(const char *s);
feof
函数说明: feof
。
/*************头文件*****************/#include <stdio.h>
/****************************** 函数名称:feof* 函数入口:stream: 这是指向 FILE 对象的指针,该 FILE 对象标识了流。* 函数出口:当设置了与流关联的文件结束标识符时,该函数返回一个非零值,否则返回零。* 函数说明:测试给定流 stream 的文件结束标识符。* ***************************/
int feof(FILE *stream);
示例代码:
说明: 示例中文件名称为test.txt,内部操作数据为以下内容
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL
示例1:使用fgetc读到文件结束并逐个使用fputc打印
#include "stdio.h"void main(void)
{FILE *fp=fopen("./test.txt","r");int c=0;while(!feof(fp)){c=fgetc(fp);fputc(c,stdout);}fclose(fp);
}
运行结果:
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL
�
运行结果分析:
文件最后会多读出一次文件结束符
由于feof不会偏移指针,而且当使用feof进行判断文件结束时,是从文件流的0位置开始而不是文件中第一个字符的位置,当先使用feof判断文件结束符 在使用fgetc或者其他读函数(可向下偏移指针流),函数会多进行一次读取,而该次读取将会超过文件。从而读出未知符号。文件结束符不会出现在文件中,而是出现在文件流中。以下改进多读一次代码:
#include "stdio.h"#define LOG(msg,...) printf("[%s][%d]:"msg"",__FUNCTION__,__LINE__,##__VA_ARGS__)
void main(void)
{FILE *fp=fopen("./test.txt","r");//假设文件中写入strlen(123456)+1个字符即7个6+"\0"int c=0;LOG("%ld\r\n",ftell(fp));//起始位置验证指向流的0位置while(1){c=fgetc(fp);//每次指向流的位置加一if(feof(fp)){break;}//fputc(c,stdout);//完美只打印123456LOG("%c--%ld\r\n",c,ftell(fp));//将会打印7次(获取但获取当前指针流位置函数)}fclose(fp);
}
假设文件中有123456\0EOF
运行结果:
使用fputc打印:123456
使用LOG打印:
[main][19]:0
[main][30]:1–1
[main][30]:2–2
[main][30]:3–3
[main][30]:4–4
[main][30]:5–5
[main][30]:6–6
[main][30]:–7
运行结果分析:
可以看见LOG打印了7次而fputc值打印了6次,结果分析fputc
使用fgetc先指向文件流中1位置打印1,再指向文件流中的2位置打印2,依次向下直到遇见文件中\0该内容无法显示fputc展现因此默认为输出为空。
LOG分析,当fgetc指向文件流中1位置打印1此时使用ftell获取的文件流位置为1,依次类推,当文件流位置指向\0时文件流为7,而此时%c无法打印\0,此时再使用fgetc将会指向文件外内容,从而文件流中生成EOF,造成退出。
同理分析以上内容其实都是打印了7次,只是fputc没有凸显\0那次打印。
将LOG修改为此语句printf(“%c”,c);结果同fputc
以上方法完美修复了案例一种使用feof多读出一次的情况,该案例原始就是写入例如strlen(123456)+1(使用strlen+1将会将字符串结束符写入文件),因此读出了7次,想要修复该BUG只需要,使用先偏移指针,再使用feof。
示例2:fgets读取文件字符串
#include "stdio.h"void main(void)
{FILE *fp=fopen("./test.txt","r");char stdbuf[6]={0};fgets(stdbuf,5,fp);//读取到n-1、末尾或者错误会停止(只会读出5-1个字符)fputs(stdbuf,stdout);fputc('\n',stdout);fclose(fp);
}
运行结果:
$GPG
(换行符\n)
示例3:getc位置递增演示
#include "stdio.h"void main(void)
{char stdbuf[6]={0};FILE *fp=fopen("./test.txt","r");int ch=getc(fp);fputc(ch,stdout);fputc('\n',stdout);// 第一次读出ch=getc(fp);fputc(ch,stdout);fputc('\n',stdout);//第二次读出ch=getc(fp);fputc(ch,stdout);fputc('\n',stdout);//第三次读出fclose(fp);
}
运行结果:
$
G
P
(换行符\n)
示例4:fputs测试
#include "stdio.h"void main(void)
{char buf[1024]={0};FILE *fp=fopen("./test.txt","r"); fgets(buf,1024,fp);//虽然读到的是1024个字节但是当遇到文件结束符将会停止fputs(buf,stdout);fclose(fp);
}
运行结果:
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL
示例5:getchar与putchar
#include "stdio.h"void main(void)
{char buf[1024]={0};int ch=getchar();ch=putchar(ch);putchar('\n');printf("%c\r\n",ch);
}
运行结果:(以在终端输入 5为示例)
5
5
5
示例6:puts与putc
#include "stdio.h"void main(void)
{int a='a';putc(a,stdout);//默认以int强转字符输出putc('\n',stdout);//打印\nputs("123456");//默认输出到标准输出流
}
运行结果:
a
123456
示例7:fgetc
#include "stdio.h"void main(void)
{int ch=getc(stdin);printf("%c\r\n",ch);
}
运行结果:(以终端输入5位例)
5
5
示例8:ungetc
#include "stdio.h"int main ()
{FILE *fp;int c;char buffer [256];fp = fopen("test.txt", "r");if( fp == NULL ){perror("打开文件时发生错误");return(-1);}while(1){c = getc (fp);if(feof(fp)){break;}if( c == '$' ){ungetc ('+', fp);}else{ngetc(c, fp);}fgets(buffer, 255, fp);fputs(buffer, stdout);}return(0);
}
运行结果:
+GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,0000*1F$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL
结果分析:
只会将流中的字符替换,不会修改文件中的字符。
示例9:r+是追加还是新建?
#include "stdio.h"int main ()
{FILE *fp;int c;char buffer [256];fp = fopen("test.txt", "r+");fputs("123456",fp);fclose(fp);//将流指向的位置偏移回来fp = fopen("test.txt", "r");fgets(buffer,255,fp);fputs(buffer,stdout);fclose(fp);return(0);
}
运行结果:
123456,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,0000*1F$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL
运行结果分析:
新写入的会进行覆盖式写入 如果不覆盖需要遍历到文件尾的位置进行写入。
示例10:fgets遇\0结束?
#include "stdio.h"int main ()
{FILE *fp;int a=0;int c=0;char buf[]="$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,, NULL";char buffer [1024];fp = fopen("test.txt", "w+");//新建文件fwrite(buf,strlen(buf)+1,1,fp);//注意使用strlen+1将会在文件尾默认写入\0fclose(fp);//关闭将流的指针复位fp = fopen("test.txt", "a+");//在文件尾追加如123456fputs("123456",fp);fclose(fp);//复位流的位置fp = fopen("test.txt", "r");while(1)//使用fgetc读{c=fgetc(fp);if(feof(fp)){break;}a++;fputc(c,stdout);}printf("\r\n");printf("%d\r\n",a);//验证读大字节大小fclose(fp);//复位流指针fp = fopen("test.txt", "r");//使用fgets读fgets(buffer,1024,fp);fputs(buffer,stdout);fclose(fp);return(0);
}
运行结果:
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL123456
145
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL
运行结果分析:
可以看到使用fgetc打印了出了123456,而使用fgets没有打印出123456,原因就是fgets遇到\0将不在打印。
示例11:fgets从标准输入流写入时不足设置长度将会读入回车
#include "stdio.h"int main ()
{char a[10];for (int i = 0; i < 10; ++i)a[i] = '1';fgets(a, 5, stdin);for (int i = 0; i < 10; ++i)printf(":[%d]%c:\n", i,a[i]);return(0);
}
运行结果:
当从终端输入55555时效果
:[0]5:
:[1]5:
:[2]5:
:[3]5:
:[4]:
:[5]1:
:[6]1:
:[7]1:
:[8]1:
:[9]1:
当从终端输入5时效果:
5
:[0]5:
:[1]
:
:[2]:
:[3]1:
:[4]1:
:[5]1:
:[6]1:
:[7]1:
:[8]1:
:[9]1:
运行结果分析:
此例中fgets中要求获取5个字符大小,到时当输入5个字符时只会获取4个另一会添加一个\0.
当输入字符数小于n-1时将会将输入时的回车符读入。
C语言文件操作笔记-1相关推荐
- C语言文件操作解析(二)【转载】
http://www.cnblogs.com/dolphin0520/archive/2011/10/05/2199598.html C语言文件操作解析(二) C语言中对文件进行操作必须首先打开文件, ...
- C语言文件操作解析(二)
C语言文件操作解析(二) C语言中对文件进行操作必须首先打开文件,打开文件主要涉及到fopen函数.fopen函数的原型为 FILE* fopen(const char *path,const cha ...
- C语言文件操作函数大全(看到总结的真的很好,就转载贡献给大家了)
C语言文件操作函数大全 clearerr(清除文件流的错误旗标) 相关函数 feof 表头文件 #include<stdio.h> 定义函数 void clearerr(FILE * st ...
- c语言计算文件摘要值,c语言文件操作摘要.ppt
c语言文件操作摘要 第十章 文件 10.1 C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 文件处理方法 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区 非 ...
- C语言文件操作解析(一)
C语言文件操作解析(一) 在讨论C语言文件操作之前,先了解一下与文件相关的东西. 一.文本文件和二进制文件 文本文件的定义:由若干行字符构成的计算机文件,存在于计算机系统中.文本文件只能存储文件中的有 ...
- c语言全文件操作函数,C语言文件操作函数大全
C语言 文件操作函数大全 C语言文件操作函数 2007-10-17 19:21 13.1C语言文件 1,两种文件存取方式(输入,输出方式) 顺序存取 直接存取 2,数据的两种存放形式 文本文件 二进制 ...
- C语言文件英文,c语言文件操作(国外英文资料).doc
c语言文件操作(国外英文资料) 韧仔欠鳖佳刀寺男拒姚友畔庶炳告舞漾容验熬销避暇庆茅奠哑栓障于筏茸兔厘万寿日击悯汤糠毛塞丈河汤忧寸绞忧择曹酪泛磋牵卧国叛株咙麓独檀烈钎熬酪夫栓线夹蔗屏矾疙陋柱狂茅悬匈队八 ...
- 基于存储的C语言文件操作常规问题分析(文本文件与二进制文件)
基于存储的C语言文件操作常规问题分析(文本文件与二进制文件) 问题描述 文本文件与二进制文件 数据写入文本乱码问题 fopen和open 流式文件操作常用函数 直接I/O文件操作常用函数 问题描述 我 ...
- c语言创建文件存放,C语言文件操作
C语言文件操作 常见硬件设备所对应的文件 文件 硬件设备 stdin 标准输入文件,一般指键盘:scanf().getchar() 等函数默认从 stdin 获取输入. stdout 标准输出文件,一 ...
最新文章
- 查找txt中的中文字符_找出nginx请求日志中某个url请求总次数排名前十的ip地址...
- 华为路由器qos car+nat+dhcp+vlan配置心得
- python3安装pip3-Python3中安装pip3
- lLinux 下 Stress 压力测试工具
- Python常见的数据类型【数字、布尔、字符串、列表和元组、字典】
- eclipse lombok插件安装_便捷开发,解放双手,lombok插件
- mvc html根目录,c#-路由到ASP.NET MVC中的根目录
- 今日代码(20201003)--简单爬虫
- 深入浅出 Java Concurrency (6): 锁机制 part 1[转]
- RESTful API 设计思考
- poj3616(Milking Time)
- 调试时遇到 调试源程序时Loaderlock 的解决办法
- Tera Term 工具的使用
- 第8章 IP代理使用技巧与实战(8.1 结合Requests库使用IP代理)
- 教妹学Java:不可不知的 Unicode 之锟斤拷
- 蔡康永的201堂情商课
- ,片片鳞甲都烁烁生辉
- Cloudera简介和安装部署概述
- ElasticSearch创建索引:[hotel/6g9tufKRuWDdWfgE_F30Q] ElasticsearchStatusException[Elasticsearch exception
- supermap+openlayers距离和面积测算