linux 文件操作(标准I/O)

linux 文件操作(标准I/O)

一、简述

标准库的I/O函数:

fopen(), fread(), fwrite(), fseek(), fclose(),fprintf(),fscanf(),ftell(),rewind()

格式化字符串:

sprintf(),sscanf()

系统I/O和标准I/O区别:

  1. 移植性
    系统函数移植性有限,标准函数移植性高。
  2. 文件IO层次
    系统IO函数为低级,标准IO函数为高级,
    区分标准:低级文件IO运行在内核态,高级文件IO运行在用户态。
  3. 缓冲区
    系统函数不带缓冲区,标准函数自带缓冲区(4k)。(按照每次读1M的速度读最快)

二、标准I/O

1. fopen

fopen()函数
功能 打开指定文件并获取文件结构体指针,或创建新文件
头文件 #include <stdio.h>
声明 FILE *fopen(const char *path, const char *mode)
参数
path 文件路径名称
mode 文件打开方式
返回值
成功 返回文件结构体指针
失败 返回NULL
mode 文件打开方式
		r     只读打开。流位于文件的开头。
		r+    在 r 基础上加上写权限。
		
		w  	  只写打开。如果文件存在则清空文件内容。不存在则创建。
		w+	  在 w 基础上加上读权限。
		
		a     只写追加打开。如果文件存在则保留文件内容。不存在则创建。
		a+    在 a 的基础上加上读权限。
		
		b     b (二进制文件)与上列权限搭配使用,作为最后一个字符,或作为两个字符中任意一个字符之间的字符。

2. fread

fread()函数
功能 从给定流 stream 读取数据到 ptr 所指向的内存中
头文件 #include <stdio.h>
声明 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
参数 ptr 存储读取到的数据的内存地址
size 要读取的每个元素的大小,以字节为单位
nmemb 元素的个数,每个元素的大小为 size 字节
stream 指向读取对象的文件结构体指针
返回值 成功 返回成功读取元素总数。 如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
失败 返回 0
备注 剩余数据大小 < 元素大小则无法被读取

3. fwrite

fwrite()函数
功能 将指定内存中的数据写入到文件中
头文件 #include <stdio.h>
声明 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
参数 ptr 存储需要写入的数据的内存地址
size 要写入的每个元素的大小,以字节为单位
nmemb 元素的个数,每个元素的大小为 size 字节
stream 指向写入对象的文件结构体指针
返回值 成功 返回写入元素总数。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
失败 返回 0

4. fseek

fseek()函数
功能 设置光标的位置
头文件 #include <stdio.h>
声明 int fseek(FILE *stream, long offset, int whence)
参数 stream 指向需要改变光标的对象的文件结构体指针
offset 偏移值
whence (基准点) SEEK_SET(文件头)
SEEK_CUR (光标当前位置)
SEEK_END (文件尾)
返回值
成功 返回 0
失败 返回 -1

5. fclose

fclose()函数
功能 关闭文件
头文件 #include <stdio.h>
声明 int fclose(FILE *fp)
参数 fp 指向需要关闭的文件的结构体指针
返回值
成功 返回 0
失败 返回 -1

6. fprintf

fprintf()函数
功能 以文本形式,按照一定格式向文件写入数据
头文件 #include <stdio.h>
声明 int fprintf(FILE *stream, const char *format, ...)
参数 stream 指向写入的文件的结构体指针
format 占位符
... 与占位符相对应的变量名
返回值 成功 成功写入的字节数
失败 返回 -1

7. fscanf

fscanf()函数
功能 以文本形式,从文件中按照一定格式读取文件内容到变量中
头文件 #include <stdio.h>
声明 int fscanf(FILE *stream, const char *format, ...)
参数 stream 指向要读取的文件的结构体指针
format 占位符
... 与占位符相对应的变量名
返回值 成功 成功读取的字节数
失败 返回 -1
占位符(部分) 演示如下demo2 demo3
		%*s 或 %d          跳过该类型的数据   (到空格或\t止)        
		%[width]s		   读指定宽度的数据               
		%[a-z]             匹配 a 到 z 中任意字符(尽可能多的匹配,不区分大小写)
		%[aBc]			   匹配 a 、 B 、 c 中的一员,贪婪性
		%[^a]			   匹配非 a 的任意字符,贪婪性
		%[^a-z]     	   表示读取除 a-z 以外的字符

8. fgets

功能:从指定的流中读取一行数据,当读取(n-1)个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,加上一个 ‘\0’ 成功返回
声明char *fgets(char *str, int n, FILE *stream);
n:读取的最大字符数(包括 '\0’ ),通常使用 sizeof(str)

注意:

  1. 当行字符(算上 ‘\n’ )大于等于 最大读取字符时,读取n-1个字符,并自动加上字符串结束符 ‘\0’。由于未读取到换行符,下次继续延续上一次读结束的位置继续往下读
  2. 最大读取字符时 大于 当行字符(算上 ‘\n’2时 ,读取n-2个字符,n-1位置添加 ‘\0’n位置读取 ‘\n’
  3. 失败或读到文件结尾返回NULL。因此不能直接通过fgets的返回值来判断函数是否是出错而终止的,应该借助feof函数或者ferror函数来判断

总结来说fgets 最多只能读入n-1个字符,最后一个字符后自动添加 ‘\0’,如果最后一个字符为 ‘\n’,则在 ‘\n’ 前添加 ‘\0’

9. ftell

ftell()函数
功能 获取光标的位置(相对开头)
头文件 #include <stdio.h>
声明 long ftell(FILE *stream)
参数 stream 指向要获取光标位置的文件的结构体指针
返回值 成功 相对文件开头的字节数(包括\0)
失败 返回 -1

10. rewind

rewind()函数
功能 将光标调至文件开头
头文件 #include <stdio.h>
声明 void rewind(FILE* stream)
参数 stream 文件结构体指针
返回值
demo1 思路:
1. fopen()   创建文件
2. fwrite()	 写入数据
3. ftell() 	 获取文件大小
4. rewind()  将光标调回文件头
5. fread()   读取数据并打印
6. fprintf() 写入数据
7. rewind()  将光标调回文件头
8. fscanf()  读取数据并打印
9. fclose()  关闭文件
#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *w_buf = "hallo world!";
	char r_buf[128] = {0};	
	int len = 0;
	char *send = " fprintf success!"; 	

	if ((fp = fopen("./file", "w+")) == NULL) {
		printf("error from fopen\n");
	}

	if (fwrite(w_buf, strlen(w_buf), 1, fp) != 1) {
		printf("error from fwrite\n");
	}

	len = ftell(fp);
	if (len == -1) {
		printf("error from ftell\n");
	} else {
		printf("len = %d\n",len);
	}

	rewind(fp);	

	if (fread(r_buf, len, 1, fp) != 1) {
		printf("error from fread\n");
	} else {
		printf("%s\n", r_buf);
	}
	
	if (fprintf(fp, "%s", send) == -1) {
		printf("error from fprintf\n");
	} else {
		rewind(fp);
		if (fscanf(fp, "%[^\t]s", r_buf) == -1) {
			printf("error from fscanf\n");
		} else {
			printf("%s\n", r_buf);
		}
	}
			
	fclose(fp);	

	return 0;
}

运行结果:

三、格式化字符串函数
sprintf()函数
功能 将变量按照一定的格式合并成字符串形式
头文件 #include <stdio.h>
声明 int sprintf(char* str, const char* format, …)
参数 str 合成目标字符串首地址
format 占位符
... 与占位符相对应的变量名
返回值 成功 目标字符串实际长度
失败 返回 -1
备注 匹配到字符串结束符 \0 结束

.
.

sscanf()函数
功能 从字符串中按照格式读取数据至变量中
头文件 #include <stdio.h>
声明 int sscanf(char* str, const char* format, ...)
参数 str 字符串首地址
format 占位符
... 与占位符相对应的变量名
返回值 成功 读取数据赋值给变量个数
str 为空字符串时 返回 -1
备注 当匹配到与对应占位符格式不一致时结束
占位符(部分)
        到空格或\t或类型不同结束本个占位符的匹配               
		%*s 或 %d          跳过该类型的数据      
		%[width]s		   读指定宽度的数据               
		%[a-z]             匹配 a 到 z 中任意字符   
		%[aBc]			   匹配 a 、 B 、 c 中的一员,贪婪性
		%[^a]			   匹配非 a 的任意字符,贪婪性
		%[^a-z]     	   表示读取除 a-z 以外的字符
demo2 思路:
sprintf()用法:
			 1. demo1()   格式化字符串
			 2. demo2()   接拼字符串   
		     3. demo3()   数字转换成字符串格式   
#include <stdio.h>

void demo1()	
{
	char buf[128] = {0};
	
	sprintf(buf, "hallo %s", "world!");
	printf("buf1 = %s\n", buf);
}

void demo2()	
{
	char *str1 = "hallo";
	char *str2 = "world!";
	char buf[128] = {0};
	
	sprintf(buf, "%s %s", str1, str2);
	printf("buf2 = %s\n", buf);
}

void demo3()	
{
	int num = 123;
	char buf[128] = {0};
	
	sprintf(buf, "%d", num);
	printf("buf3 = %s\n", buf);
}

int main()
{
	demo1();
	demo2();
	demo3();	
	
	return 0;
}

运行结果:
在这里插入图片描述

demo3
#include <stdio.h>

void demo1()	//%*s 或 %d          跳过该类型的数据
{
	char *str = "Ab12 cd";
	char buf[128] = {0};

	sscanf(str, "%*s%s", buf);
	printf("%s\n", buf);	// %s到空格止  buf = cd
}

void demo2()	//%[width]s		   读指定宽度的数据 
{
        char *str = "hallo world!";
        char buf[128] = {0};

        sscanf(str, "%8s", buf);
        printf("%s\n", buf);	//到空格止   buf = hallo
}

void demo3()	%[a-z]             匹配 a 到 z 中任意字符
{
        char *str = "ab12cD!";
        char buf[128] = {0};

        sscanf(str, "%[a-z]", buf);
        printf("%s\n", buf);	// 1 非 a-z  buf = ab
}

void demo4()	//%[aBc]			   匹配 a 、 B 、 c 中的一员,贪婪性
{
        char *str = "aB12c";
        char buf[128] = {0};

        sscanf(str, "%[aBc]", buf);
        printf("%s\n", buf);	// 1 非 aBc  buf = aB
}

void demo5()	//%[^a]			   匹配非 a 的任意字符,贪婪性
{
        char *str = "123ooo";
        char buf[128] = {0};

        sscanf(str, "%[^o]", buf);
        printf("%s\n", buf);	//匹配非o字符串   buf = 123
}

void demo6()	//%[^a-z]     	   表示读取除 a-z 以外的字符
{
        char *str = "123aBc";
        char buf[128] = {0};

        sscanf(str, "%[^a-z]", buf);
        printf("%s\n", buf);	// 匹配非a-z字符串  buf = 123
}


int main()
{
	demo1();
	demo2();
	demo3();
	demo4();
	demo5();
	demo6();

	return 0;
}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值