Linux利用标准c库对文件操作

发布时间:2024年01月18日

? ? ? 这里的思路和之前的‘Linux下文件的创建写入读取编程‘的思路是一样的,都是从介绍API的函数功能开始。都是在Linux下操作文件,但是前者是UNIX系统调用函数,后者是ANSIC标准中的C语言库函数。它们有着不同的适用范围,具体有不同,在概念上我就不细说了,大家可以看看这篇博客园的博客https://www.zybuluo.com/yiltoncent/note/87461。我会从函数的使用上给大家说一说区别。

之前我们写的文件操作相关函数都是UNIX系统调用函数,如open,write,read等,这里我们要用的是标准c库对文件下的函数,如fopen,fread,fwrite,fseek等。

一、API函数的介绍

打开文档

①FILE *fopen(const char *pathname, const char *mode);

’参数

pathname:文件路径名

mode:文件模式,有以下六种

种类

功能

r

只读打开

r+

可读可写打开

w

可写打开,写入文件同时清除原文件内容

w+

可读可写;如果文件存在,写入文件同时清除原文件;如果不存在创建文件

a

可写打开,如果文件存在,在原文件尾部继续写;如果不存在创建文件

a+

可读可写打开,如果文件存在,在原文件尾部继续写;如果不存在创建文件

fopen() mode 与 open() flags的联系

fopen() mode

open() flags

r

O_RDONLY

w

O_WRONLY | O_CREAT | O_TRUNC

a

O_WRONLY | O_CREAT | O_APPEND

r+

O_RDWR

w+

O_RDWR | O_CREAT | O_TRUNC

a+

O_RDWR | O_CREAT | O_APPEND

返回值

打开成功,返回一个FILE类型指针;打开失败返回NULL

读文档

②size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数

ptr:存储读出的内容到缓冲区

size:一次读出的内容大小

nmemb:读几次

stream:指向文件结构体的指针,相当于open函数的fd,起到索引作用

返回值

读取成功,返回写入的字节数除以size(不是整数采用去尾法,如1.5,返回值就是1)

0,发生读取错误,应检查必须用feof()或ferror()来决定发生什么情况,看一下是读到了文件尾了或者有错误发生,

feof() 函数用来判断文件内部指针是否指向了文件末尾,它的原型是:

int feof (FILE * stream)

当指向文件末尾时返回非零值,否则返回零值。

ferror() 函数用来判断文件操作是否出错,它的原型是:

Int ferror (FILE* stream)

出错时返回非零值,否则返回零值。

写文档

③size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

参数

ptr:存储写入的内容到缓冲区

size:一次读写出的内容大小

nmemb:写几次

stream:指向文件结构体的指针,相当于open函数的fd,起到索引作用

成功写入,返回值为nmemb的大小;写入失败,返回值为0。

文件光标移动

④int fseek(FILE *stream, long offset, int whence);

参数

stream:指向文件结构体的指针,相当于open函数的fd,起到索引作用

offset:相对于whence偏移的位置。0,不偏移;正整数,向右偏移对应的大小;负整数,向左偏移对应的大小。

whence:光标起始位置,一共有三个选项,如下

SEET_SET???????? 文件开头

SEET_CUR???????? 文件当前位置

SEET_END???????? 文件尾部

如果成功,则返回相对于文件头的偏移量。如果出现错误,则返回-1。如果我们设置为

fseek(fp,0,SEET_END)就可以利用他的返回值来表示文件的大小了。

关闭文档

⑤int fclose(FILE *stream);

参数

stream:指向文件结构体的指针,相当于open函数的fd,起到索引作用

返回值

成功完成后,返回0;否则,返回EOF

以字符的形式读取文件

⑥int fgetc(FILE *stream);

参数

stream:指向文件结构体的指针,相当于open函数的fd,起到索引作用

返回值

成功时返回读入的字节数。错误或文件尾时返回EOF;

以字符的形式写入文件

⑦int fputs(const char *s, FILE *stream);

参数

s:要写入的字符串

stream:指向文件结构体的指针,相当于open函数的fd,起到索引作用

返回值

成功时返回写入的字节数。错误时返回EOF;

二、代码验证

1.以w+的方式创建打开新文件,并写入内容在读出

原来并没有ydlt.txt的文件,如下图

现在我们通过程序创建并打开写入内容,并读取。看一下读取的内容与写入的内容是否一致,并查看fread和fwrite的返回值

验证代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

int main()

{

FILE *fp;

char*str="yangdong is handsome";

char readBuf[128]={0};

fp=fopen("./ydlt.txt","w+");

if(fp==NULL)

{

printf("read failed\n");

exit(-1);

}

int n_write=fwrite(str,sizeof(char),100,fp);

printf("n_write=%d\n",n_write);

fseek(fp,0,SEEK_SET);

int n_read=fread(readBuf,sizeof(char)*strlen(str),100,fp);

printf("n_read=%d\n",n_read);

if(n_read==0)//判断读取是否文件操作出错导致的

{

printf("打开文件错误\n");

if(ferror(fp))//判断读取出错是否是由文件

puts("读取出错\n");

if(feof(fp)) //判断读取出错是否是由文件光标到了文件尾部导致的

puts("达到文件尾部\n");

exit(-1);

}

printf("read %s\n",readBuf);

return 0;

}

执行结果如下图所示,可以看到的文件ydlt.txt已经创建,n_write=100,n_read=5,读出的内容是yangdong is handsome

在前面我们已经说过了,n_write作为fwrite的返回值,在写入无误后返回值是nmemb的大小。程序里nmemb是100,对应n_write=100。n_read作为fread的返回值,成功读出后,其大小应该是返回写入的字节数除以size,程序里我们写入的是总大小是sizeof(char)*100,也就是100。我们读取的时候,一次的大小是“yangdong is handsome”的长度,也就是20,所以n_read=100/20=5。如果我们改一下程序,比如将fwrite(str,sizeof(char),100,fp);的100改成99,那么n_read=99/20=4.95,我们知道n_read是int型,所以对于4.95会转化成4,也就是我们前面说的去尾法。

在程序里我们在fwrite后面加了一句fseek(fp,0,SEEK_SET),它的作用就是把文件光标回到文件开头。我们知道文件写入完成后文件光标回到文件末尾,如果我们不把文件光标回到文件开头,我们读取的时候就会发生错误,现在我们把fseek(fp,0,SEEK_SET)删除。看一看现象

我们可以看到当文件光标在文件末尾的时候我们去读,会发生错误,fread的返回值是0,且通过feof()和ferror()函数用来判断到底是哪个环节出错了,最后显示是因为文件光标在文件末尾导致的出错。

2.fputc和fgetc的验证

fputc的验证

#include<stdio.h>

#include<string.h>

int main()

{

FILE*fp;

char*str="yangdong is really handsome\n";

fp=fopen("./test.txt","w+");

int n_size=strlen(str);

for(int i=0;i<n_size;i++)

{

fputc(*str,fp);//一个字节一个字节的打印到文件里面

str++;

}

fclose(fp);

return 0;

}

可以看到已经成功的写入了我们想要的内容

fgetc的验证

#include <stdlib.h>

#include<stdio.h>

int main()

{

?? FILE *fp;

?? char ch;

?? //如果文件不存在,给出提示并退出

?? if( (fp=fopen("./test.txt","r")) == NULL )

?? {

???? puts("Fail to open file!");

????? exit(-1);

??? }

??? //每次读取一个字节,直到读取完毕

??? while( (ch=fgetc(fp)) != EOF ){

??????? putchar(ch);

??? }

??? putchar('\n');? //输出换行符

??? if(ferror(fp))

??? {

??????? puts("读取出错");

??? }

??? else

??? {

??????? puts("读取成功");

}

fclose(fp);

return 0;

}

可以看到成功读取了test.txt的内容,同时虽然是EOF引起的循环结束,但是造成EOF的原因也很明显,是因为读取到了文件的末尾造成的,而不是读取出错造成的。

文章来源:https://blog.csdn.net/weixin_51374594/article/details/135651460
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。