C-读写文件和输出输出
Posted Pam
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C-读写文件和输出输出相关的知识,希望对你有一定的参考价值。
问题
一直对C操作文件(读写)很模糊,不是很清楚,现系统的梳理下,彻底弄明白
说明:
这下面的程序在VS中编写和调试
基本知识
-----打开文件-----
fopen()
可以使用fopen()函数创建新文件和打开一个已有文件
会调用初始化类型FILE类型的一个对象,类型FILE包含所有用来控制二进制流的必要信息
函数原型为:
FILE *fopen( const char * filename, const char * mode );
参数介绍:
filename:是字符串,用来命名文件
mode:访问模式,下表中介绍:
模式 | 描述 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容【覆盖】。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
若是二进制文件,则用:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
补充:
只有用 r+ 模式打开文件才能插入内容,w 或 w+ 模式都会清空掉原来文件的内容再来写,a 或 a+ 模式即总会在文件最尾添加内容,哪怕用 fseek() 移动了文件指针位置。
-----关闭文件-----
fclose()
用fclose()函数,清空缓冲区的数据,关闭文件,释放文件中所有的内存
函数原型如下:
int fclose( FILE *fp );
补充:
若关闭成功,则返回0;若关闭失败,返回EOF,EOF是一个定义在头文件stdio.h中的常量
-----写入文件-----
写入文件有很多方式,下面一一介绍:
fputc()
函数原型为:
int fputc( int c, FILE *fp );
介绍:
该函数是把参数int c的字符值写入fp指向的输入流中,若写入成功,则会返回写入字符;若写入失败,返回EOF
fputc()只能一次写入一个字符,与fputc()对应的是fgetc(),会在后面介绍
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* str = fopen("demo.txt", "w+"); if (str == EOF) { printf("打开失败!"); } printf("%c\\n", fputc(65, str)); if (fclose(str) == EOF) { printf("写入失败!"); } system("pause"); return 0; }
fputs()
函数原型:
int fputs( const char *s, FILE *fp );
介绍:
该函数是把字符串s写入到fp指向的输出流中,若写入成功,返回一个非负值;若写入失败,返回EOF
fputs()一次能写入一个字符串,与fputs()对应的是fgets(),会在后面介绍
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* str = fopen("demo.txt", "a+");//"a+"追加数据在文件中 if (str == EOF) { printf("打开失败!"); } printf("%d\\n", fputs("Helloworld", str));//写入成功后会返回一个非负值 if (fclose(str) == EOF) { printf("写入失败!"); } system("pause"); return 0; }
fprintf()
函数原型:
int fprintf(FILE *stream, const char *format, ...)
介绍:
stream:指向FILE的指针
format:指C字符串,包含了要被写入到流stream中的文本,可嵌入标签,标签可以被后面的参数中指定的值替换,并按需求格式化。
若写入成功,则返回字符总数;否则返回一个负数。与fprintf()对应的是fscanf(),会在后面介绍
标签格式以及具体说明如下:
%[flags][width][.precision][length]specifier
specifier(说明符) | 输出 |
---|---|
c | 字符 |
d 或 i | 有符号十进制整数 |
e | 使用 e 字符的科学科学记数法(尾数和指数) |
E | 使用 E 字符的科学科学记数法(尾数和指数) |
f | 十进制浮点数 |
g | 自动选择 %e 或 %f 中合适的表示法 |
G | 自动选择 %E 或 %f 中合适的表示法 |
o | 有符号八进制 |
s | 字符的字符串 |
u | 无符号十进制整数 |
x | 无符号十六进制整数 |
X | 无符号十六进制整数(大写字母) |
p | 指针地址 |
n | 无输出 |
% | 字符 |
flags(标识) | 描述 |
---|---|
- | 在给定的字段宽度内左对齐,默认是右对齐(参见 width 子说明符)。 |
+ | 强制在结果之前显示加号或减号(+ 或 -),即正数前面会显示 + 号。默认情况下,只有负数前面会显示一个 - 号。 |
(space) | 如果没有写入任何符号,则在该值前面插入一个空格。 |
# | 与 o、x 或 X 说明符一起使用时,非零值前面会分别显示 0、0x 或 0X。 与 e、E 和 f 一起使用时,会强制输出包含一个小数点,即使后边没有数字时也会显示小数点。默认情况下,如果后边没有数字时候,不会显示显示小数点。 与 g 或 G 一起使用时,结果与使用 e 或 E 时相同,但是尾部的零不会被移除。 |
0 | 在指定填充 padding 的数字左边放置零(0),而不是空格(参见 width 子说明符) |
width(宽度) | 描述 |
---|---|
(number) | 要输出的字符的最小数目。如果输出的值短于该数,结果会用空格填充。如果输出的值长于该数,结果不会被截断。 |
* | 宽度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。 |
.precision(精度) | 描述 |
---|---|
.number | 对于整数说明符(d、i、o、u、x、X):precision 指定了要写入的数字的最小位数。如果写入的值短于该数,结果会用前导零来填充。如果写入的值长于该数,结果不会被截断。精度为 0 意味着不写入任何字符。 对于 e、E 和 f 说明符:要在小数点后输出的小数位数。 对于 g 和 G 说明符:要输出的最大有效位数。 对于 s: 要输出的最大字符数。默认情况下,所有字符都会被输出,直到遇到末尾的空字符。 对于 c 类型:没有任何影响。 当未指定任何精度时,默认为 1。如果指定时不带有一个显式值,则假定为 0。 |
.* | 精度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。 |
length(长度) | 描述 |
---|---|
h | 参数被解释为短整型或无符号短整型(仅适用于整数说明符:i、d、o、u、x 和 X)。 |
l | 参数被解释为长整型或无符号长整型,适用于整数说明符(i、d、o、u、x 和 X)及说明符 c(表示一个宽字符)和 s(表示宽字符字符串)。 |
L | 参数被解释为长双精度型(仅适用于浮点数说明符:e、E、f、g 和 G)。 |
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* str = fopen("demo.txt", "a+");//"a+"追加数据在文件中 if (str == EOF) { printf("打开失败!"); } //追加数据时换行; fputs("\\n", str); printf("%d\\n", fprintf(str,"He%s wor%s !","llo","ld"));//写入成功后会返回一个非负值 if (fclose(str) == EOF) { printf("写入失败!"); } system("pause"); return 0; }
说明:
若想要在追加文件时,换行:
//追加数据时换行; fputs("\\n", str);
putc()
函数声明:
int putc(int char, FILE *stream)
介绍:
将参数char指向的字符(无符号字符)写入到指定的stream中,并把位置标识符向前移。每次写入单个字符,和fputc()功能大致一样,与之相对的是getc(),会在下面介绍
- char -- 这是要被写入的字符。该字符以其对应的 int 值进行传递。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。
返回值:若成功则返回写入的字符,若失败,返回EOF
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { FILE* fp; int ch; fp = fopen("file.txt", "w"); for (ch = 33; ch <= 100; ch++) { printf("%c",putc(ch, fp)); } fclose(fp); return(0); }
fwrite()
函数声明:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
介绍:
把ptr所指向数组中的数据写入到stream中,与fwrite()对应的是fread(),在下面会详细介绍
size_t:定义为 long long unsigned int,函数sizeof()返回类型就是这个
ptr:指向要被写入的元素数组的指针
size:要被写入的每个元素的大小,以字节为单位
nmemb:元素的个数,每个元素的大小为size字节
stream:指向FILE的指针
返回值:若成功,返回一个size_t对象,表示元素的总数,若该数字与nmemb参数不同,会报错
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* fp; char str[] = "This is runoob.com"; fp = fopen("file.txt", "w"); printf("%ld",fwrite(str, sizeof(str), 1, fp));//若成功,返回1,即元素的个数 fclose(fp); return(0); }
-----读取文件-----
fgetc()
函数原型为:
int fgetc(FILE *stream)
介绍:
从指定的流stream中获取下一个字符,并将位置标识符向前移动?
返回值:以无符号chat强制转换int返回值,返回字符;若失败,则返回EOF
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* fp; int c; int n = 0; fp = fopen("demo.txt", "r"); if (fp == NULL) { perror("打开文件时发生错误"); return(-1); } do { c = fgetc(fp);//读出一个字符后,位置指针自动后移 if (feof(fp)) { break; } printf("%c", c); } while (1); fclose(fp); system("pause"); return(0); }
fgets()
函数原型:
char *fgets(char *str, int n, FILE *stream)
介绍:
该函数从指定流stream中读取一行,并存在str所指向的字符串内,当读取(n-1)个字符时,或者读到换行符时,或达到文件末尾时,会停止
str:指向一个字符数组的指针,该数组中存储了要读取的字符串
n:这是要读取的最大字符数(包括最后的空字符),通常指以str传递的数组的长度
stream:指向FILE的指针
返回值:若返回成功,返回相同的str参数,若到达文件尾或者没有读取到任何字符,str内容不变,返回空指针;若返回出错,返回空指针
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* fp; char str[60]; /* 打开用于读取的文件 */ fp = fopen("demo.txt", "r"); if (fp == NULL) { perror("打开文件时发生错误"); return(-1); } if (fgets(str, 60, fp) != NULL) { /* 向标准输出 stdout 写入内容 */ puts(str);//此时对这个函数还不是很熟悉后面会详细介绍 } fclose(fp); system("pause"); return(0); }
这里用到了puts()函数,此时还不太了解,本来是想梳理一下文件管理,看来最基本的输入输出也得系统的学习一下,该函数后面会详细介绍
fscanf()
函数原型:
int fscanf(FILE *stream, const char *format, ...)
介绍:
从流stream中读取,并格式化输入到format指定的变量中,读取时遇到空格自动结束
参数大致和fprintf()一致,标签可以被后面的参数中指定的值替换,并按需求格式化
返回值:若成功,则返回成功匹配和赋值的个数;若到达文件末尾或发生读错误,则返回 EOF
format说明符和具体介绍如下:
[=%[*][width][modifiers]type=]
参数 | 描述 |
---|---|
* | 这是一个可选的星号,表示数据是从流 stream 中读取的,但是可以被忽视,即它不存储在对应的参数中。 |
width | 这指定了在当前读取操作中读取的最大字符数。 |
modifiers | 为对应的附加参数所指向的数据指定一个不同于整型(针对 d、i 和 n)、无符号整型(针对 o、u 和 x)或浮点型(针对 e、f 和 g)的大小: h :短整型(针对 d、i 和 n),或无符号短整型(针对 o、u 和 x) l :长整型(针对 d、i 和 n),或无符号长整型(针对 o、u 和 x),或双精度型(针对 e、f 和 g) L :长双精度型(针对 e、f 和 g) |
type | 一个字符,指定了要被读取的数据类型以及数据读取方式。具体参见下一个表格。 |
类型 | 合格的输入 | 参数的类型 |
---|---|---|
c | 单个字符:读取下一个字符。如果指定了一个不为 1 的宽度 width,函数会读取 width 个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。 | char * |
d | 十进制整数:数字前面的 + 或 - 号是可选的。 | int * |
e,E,f,g,G | 浮点数:包含了一个小数点、一个可选的前置符号 + 或 -、一个可选的后置字符 e 或 E,以及一个十进制数字。两个有效的实例 -732.103 和 7.12e4 | float * |
o | 八进制整数。 | int * |
s | 字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。 | char * |
u | 无符号的十进制整数。 | unsigned int * |
x,X | 十六进制整数。 |
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { char str1[10], str2[10], str3[10]; int year; FILE* fp; fp = fopen("file.txt", "w+"); fputs("We are in 2014", fp); rewind(fp); fscanf(fp, "%s %s %s %d", str1, str2, str3, &year); printf("Read String1 |%s|\\n", str1); printf("Read String2 |%s|\\n", str2); printf("Read String3 |%s|\\n", str3); printf("Read Integer |%d|\\n", year); fclose(fp); system("pause"); return(0); }
这里用到了rewind()函数,下面来学习一下
getc()
函数声明:
int getc(FILE *stream)
介绍:
从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动,和fgetc类似
返回值:若返回成功,则返回读取到的字符;若到达文件末尾或发生读错误,则返回 EOF。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { char c; printf("请输入字符:"); c = getc(stdin); printf("输入的字符:"); putc(c, stdout); return(0); }
这里用到了stdin和stdout,需要说明一下:
标准文件
stdin和stdout其实都是一个fp,指向一个流,stdin指的是一个输入流,stdout指的就是一个输出流
更多介绍:
C 语言把所有的设备都当作文件。所以设备(比如显示器)被处理的方式与文件相同。以下三个文件会在程序执行时自动打开,以便访问键盘和屏幕。
标准文件 | 文件指针 | 设备 |
---|---|---|
标准输入 | stdin | 键盘 |
标准输出 | stdout | 屏幕 |
标准错误 | stderr | 您的屏幕 |
fread()
函数声明:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
介绍:
将给定stream读取到ptr所指向的数组中
参数和fwrite()中的参数中类似,不再赘述
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* fp; char c[] = "This is runoob"; char buffer[20]; /* 打开文件用于读写 */ fp = fopen("file.txt", "w+"); /* 写入数据到文件 */ fwrite(c, strlen(c) + 1, 1, fp); /* 查找文件的开头 */ fseek(fp, 0, SEEK_SET); /* 读取并显示数据 */ fread(buffer, strlen(c) + 1, 1, fp); printf("%s\\n", buffer); fclose(fp); return(0); }
-----其他文件函数-----
rewind()
函数原型:
void rewind(FILE *stream)
介绍:
该函数将文件内部的位置指针重新指向一个流的开头,可以理解成,重新将位置指针重新移动到开始
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { char str[] = "This is runoob.com"; FILE* fp; int ch; /* 首先让我们在文件中写入一些内容 */ fp = fopen("file.txt", "w"); fwrite(str, 1, sizeof(str), fp); fclose(fp); fp = fopen("file.txt", "r"); while (1) { ch = fgetc(fp); if (feof(fp)) { break; } printf("%c", ch); } rewind(fp); //重新将位置指针移动至开始 printf("\\n"); while (1) { ch = fgetc(fp); if (feof(fp)) { break; } printf("%c", ch); } fclose(fp); system("pause"); return(0); }
这里用到了feof()函数,我们在下面详细介绍:
feof()
函数声明:
int feof(FILE *stream)
介绍:
该函数是测试给定stream的文件结束标识符,
返回值:若位置指针指到了文件结束标识符时,即该流读完时,返回一个非零值;否则返回0
例子就是上面的例子
fseek()
函数声明:
int fseek(FILE *stream, long int offset, int whence)
介绍:
设置stream的文件位置为给定的偏移offset,offset指从给定的whence位置开始查找的字节数
stream:指向FILE的指针
offset:相对whence的偏移量,以字节为单位;负号前移,正号后移。
whence:表示开始添加偏移offset的位置,一般指下面常量之一:
常量 | 描述 |
---|---|
SEEK_SET | 文件的开头 |
SEEK_CUR | 文件指针的当前位置 |
SEEK_END | 文件的末尾 |
SEEK_END 为文件结尾时,偏移量应该为负值,指从文件末尾向前偏移这个结构体那么多的长度给文件指针fp
返回值:若成功,则返回0;否则返回非零值
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* fp; int c; fp = fopen("file.txt", "w+"); fputs("This is runoob.com", fp); fseek(fp, 8, SEEK_SET); fputs(" C Programming Langauge", fp); fclose(fp); fp = fopen("file.txt", "r"); while (1) { c = fgetc(fp); if (feof(fp)) { break; } printf("%c", c); } fclose(fp); return(0); }
这里我们写入文件后,重新指定位置指针,在第8个位置,然后从这里开始写入
ftell()
函数声明:
long int ftell(FILE *stream)
介绍:
该函数能返回给定流stream的当前文件位置
返回值:返回位置标识符的当前值 【字节表示】;若出错,返回-1L
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { FILE* fp; int len; fp = fopen("file.txt", "r"); if (fp == NULL) { perror("打开文件错误"); return(-1); } fseek(fp, 0, SEEK_END); len = ftell(fp); //返回文件位置的结尾 fclose(fp); printf("file.txt 的总大小 = %d 字节\\n", len); return(0); }
截止到这里,关于文件的读写,已经有一个大致的了解,下面再梳理一下输入输出:
输入输出
-----输入-----
puts()
函数声明:
int puts(const char *str)
介绍:
该函数将一个字符串写入标准输出中,直到空字符,但不包括空字符。换行符会被追加到输出中
str -- 这是要被写入的 C 字符串
返回值:若成功,返回一个非负值【字符串长度(包括末尾\\0)】;若出错,则返回EOF
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { char str1[15]; char str2[15]; strcpy(str1, "RUNOOB1"); strcpy(str2, "RUNOOB2"); puts(str1); puts(str2); return(0); }
这里用到了strcpy()函数,下面介绍一下
---strcpy()---
函数声明:
char *strcpy(char *dest, const char *src)
介绍:
该函数把src指向的字符串复制到dest中,用到了<string.h>库
dest:指存储数据的目标数组
src:要复制的字符串
返回值:返回一个指向最终目标字符串dest的指针
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { char src[40]; char dest[100]; memset(dest, \'\\0\', sizeof(dest));//将\'\\0\'作为结尾符,添加到最后面 strcpy(src, "This is runoob.com"); strcpy(dest, src); printf("最终的目标字符串: %s\\n", dest); return(0); }
这里又用到了memset()函数,下面来看一下该函数:
----memset()----
函数声明:
void *memset(void *str, int c, size_t n)
介绍:
该函数复制字符c(一个无符号字符)到参数str所指向的字符串的前n个字符
- str -- 指向要填充的内存块。
- c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
- n -- 要被设置为该值的字符数。
返回值:返回一个指向存储区str的指针
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { char str[50]; strcpy(str, "This is string.h library function"); puts(str); memset(str, \'$\', 7); puts(str); return(0); }
getchar()
函数声明:
int getchar(void)
介绍:
从标准输入 stdin 获取一个字符(一个无符号字符),这等同于 getc 带有 stdin 作为参数
从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。您可以在循环内使用这个方法,以便从屏幕上读取多个字符。
返回值:若成功,返回对应的字符;若到达文件末尾或发生读错误,则返回 EOF
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { char c; printf("请输入字符:"); c = getchar(); printf("输入的字符:"); putchar(c); return(0); }
-----输出-----
gets()
函数声明:
char *gets(char *str)
介绍:
从标准输入 stdin 读取一行,并把它存储在 str 所指向的字符串中。当读取到换行符或者到达文件末尾时,它会停止,具体视情况而定
返回值:若成功,该函数返回 str。如果发生错误或者到达文件末尾时还未读取任何字符,则返回 NULL。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { char str[50]; printf("请输入一个字符串:"); gets(str); printf("您输入的字符串是:%s", str); return(0); }
putchar()
函数声明:
int putchar(int char)
介绍:
把参数 char 指定的一个字符(一个无符号字符)写入到标准输出 stdout 中,该字符以其对应的 int 值进行传递
把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。您可以在循环内使用这个方法,以便在屏幕上输出多个字符。
返回值:若成功,则返回写入的字符;若发生错误则返回 EOF
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { char ch; for (ch = \'A\'; ch <= \'Z\'; ch++) { putchar(ch); } return(0); }
参考
1、C语言
5、C 文件读写
以上是关于C-读写文件和输出输出的主要内容,如果未能解决你的问题,请参考以下文章
C 语言文件操作 ( 配置文件读写 | 框架搭建 | 头文件定义 | 头文件导入限制 | 兼容 C++ 语言 | 函数形参输入输出属性注释)
c语言读写csv文件问题,输出不出来,用f11看说buf烫,请问是啥问题?