LinuxC语言文件i/o笔记(第十七天)

最近忙着比赛和学单片机了,原本想着不写博客了,但是发现不自己写一下相关的笔记,有点记不住这些东西,就还是抽时间写了。

标准i/o:

流的打开和关闭:

c语言和c++语言一致,也有关于文件的操作函数,也同要包含标准输入流什么的。

打开流:

在c语言中,我们通过 fopen 关键字打开标准i/o流:

FILE *fopen(const char *path,const char *mode);

第一个参数是文件名/地址,第二个参数为打开方式,分为六种:"r"、"r+"、"w"、"w+"、"a"、"a+",如果要打开二进制文件就在模式后面加个b,如"rb"。其中,w为只读,w+为读写,它们都要求文件存在,不然会错误;w为只写,w+为读写,它们如果没有文件会创建文件,若存在文件,则清空该文件 ;a和a+和w一致,但是是从文件末端写入数据,而且不清空原文件。

函数成功的话会返回流指针,否侧返回NULL。

cpp 复制代码
#include <stdio.h>

......

    FILE *fps

    if((fps = fopen(argv[1],"r")) == NULL){
        perror("fopen src file");
        return -1;
    }

......

fopen()函数创建的文件默认权限为0666(rw-rw-rw-)

处理错误信息:

extern int errno

errno为全局变量,存放错误的编号,错误1为无权限,11为无资源等;

void perror(const char *s);

可以打印错误信息,会先输出参数s,在输出errno的错误信息。

char *strerror(int errno);

可以根据错误号返回对应的错误信息,需要头文件<errno.h>,使用起来比上面的麻烦很多。

关闭流:

通过 fclose 关键字关闭标准i/o流:

int fclose(FILE *stream);

成功关闭会返回0,失败返回EOF,并自动设置errno。

关闭时会自动把缓冲区数据写入并释放缓冲区。

虽然程序结束后会自动关闭流,但为了规范和防止出问题,还是要记得写fclose。

按字符输入输出:

c语言有三种输入输出方式,第一个就是按字符输入输出:

int fgetc(FILE *stream);

int getc(FILE *stream);

int getchar(void);

成功时会返回读取到的字符,到文件末尾或出错就会返回EOF。

getchar()是从标准输入流(即终端)获取一个字符。前两个函数当FILE *stream = stdin时,等同于getchar(),stdin就是终端标准流。

输出也有三个函数:

int fputc(int c,FILE *stream);

int putc(int c,FILE *stream);

int putchar(void);

成功的话返回写入的字符,出错返回EOF

putchar()等同于fputc(c,stdout),stdout为标准输出流(即终端)。

cpp 复制代码
#include <stdio.h>

int main(int argc,char *argv[]){
        FILE *fps,*fpd;
        int ch;

        if(argc < 3){
                printf("Usage : %s <sre_file> <dst_file>\n",argv[0]);
                return -1;
        }
        if((fps = fopen(argv[1],"r")) == NULL){
                perror("fopen src file");
                return -1;
        }
        if((fpd = fopen(argv[2],"w")) == NULL){
                perror("fopen src file");
                return -1;
        }
        while((ch = fgetc(fps)) != EOF){
                fputc(ch,fpd);
        }
        fclose(fps);
        fclose(fpd);
        return 0;
}

使用程序的时候要附带输入输出的文件:

bash 复制代码
./test text textcp

前者必须存在,因为用的是r只读模式,后者可以不存在,w模式若不存在文件会自动创建一个。

按行输入输出:

不好用!不好用!不好用!

使用不当会导致缓冲区溢出等。

输入函数为:

char *gets(char *a);

char *fget(char *a,int size,FILE *stream);

gets主要用于在标准输入读取一行,和c++的getline很像,但只指定了缓冲区的头地址,而无长度,就容易缓冲区溢出。

fget是从指定流中读取一行写入缓冲区,是指定大小,指定流的读取。

成功的话返回写入的缓冲区a,到末尾或出错时返回NULL。

遇到"\n"或已读取了size-1个字符时返回,末尾会自动加'\0'表示其为字符串。

其中a为char *a[],即字符串,c语言中是没有string的,所以只能使用字符数组。

输出函数和输入函数类似:

int puts(const char *a);

int fputs(const char *a,FILE *stream);

成功的话返回写入的流的字符个数,到末尾或出错时返回EOF。

puts将a输入到stdout时会追加'\n',fputs不会追加换行符。

按对象输入输出:

size_t fread(void *prt,size_t size,size_t n,FILE *fp);

size_t fwrite(const void *prt,size_t size,size_t n,FILE *fp);

数据文件为整数,就可以以整型对象去读取,若为字符,就以以字符对象读取。

prt为缓冲区,要自己先定义好,size为每个对象的大小,字符为1字节,整型为4字节,n为读取输出的对象长度,fp为输入输出流。

成功返回实际读写的对象个数,出错返回EOF。

cpp 复制代码
#include <stdio.h>
#define N 64
int main(int argc ,char *argv[]){
        FILE *fps,*fpd;
        char buf[N];
        int n;
        if(argc < 3){
                printf("Usage : %s <sre_file> <dst_file>\n",argv[0]);
                return -1;
        }
        if((fps = fopen(argv[1],"r")) == NULL){
                perror("fopen src file");
                return -1;
        }
        if((fpd = fopen(argv[2],"w")) == NULL){
                perror("fopen src file");
                return -1;
        }
        while((n = fread(buf,1,N,fps)) > 0){
                fwrite(buf,1,n,fpd);
        }
        fclose(fps);
        fclose(fpd);
        return 0;
}

fgetc/fputc 效率低但安全

fgets/fputs 效率较高,但是不安全,而且只能文本读写

fread/fwrite 效率高,安全,可以指定读取,节省内存等

流的相关操作:

刷新流:

int fflush(DILE *fp);

正常程序中,只用关闭流或程序结束的时候,缓冲区的数据才会实际写入文件,但如果遇到要长期运行的程序就会导致数据转移失败或延后,就可以对当前的输入输出流进行刷新,将缓冲区的数据马上写入实际的文件,但Linux系统只能对输出流进行刷新。

成功的时候返回0,失败返回EOF;

定位流:

long ftell(FILE *fp);

long fseek(ILE *fp,long offset,int whence);

long rewind(ILE *fp);

ftell返回的是当前读写的位置,出错返回EOF;

fseek参数为流指针、偏移量和指定位置,指定位置参数为(SEEK_SET(开始位置),SEEK_CUP(当前位置),SEEK_END(文件末尾)),成功返回流,失败为EOF。

rewind就是把文件定位回开头,即fseek(fp,0,SEEK_SET)。

判断流的出错和结束:

上面错误流讲过error函数了,就不再多讲。

判断流是否结束的函数为

int feof(FILE *fp);

返回1表示已到末尾,返回0则未到。

cpp 复制代码
#include <stdio.h>
int main(){
        FILE *fp;

        if((fp = fopen("test.txt","r+")) == NULL){
                perror("fopen");
                return -1;
        }
        fseek(fp,0,SEEK_END);
        fputc('t',fp);
        fflush(fp);
        printf("ftell(fp) = %ld\n", ftell(fp));

        if(feof(fp) == 1){
                printf("到达文件末端\n");
        }
        fclose(fp);
        return 0;
}

格式化输出:

在c语言中,我们经常用到printf进行输出,在流里,还有两种:

int fprintf(FILE *FP,const char *fmt,....);

int sprintf(char *a,const char *fmt,...);

和printf一样,fmt为"%d",time这样把像输入的东西按照%d,%s什么的格式输入进流,fprintf是输入到文件,sprintf为输入到缓冲区里。

cpp 复制代码
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
int main(){
        FILE *fp;
        int line = 0;
        char buf[64];
        time_t t;
        struct tm *tp;
        if((fp = fopen("test.txt","a+")) == NULL){
                perror("fopen");
                return -1;
        }
        while(fgets(buf,64,fp) != NULL){
                if(buf[strlen(buf) - 1] == '\n') { line++; }
        }
        while(1){
                time(&t);
                tp = localtime(&t);
                fprintf(fp,"%02d,%d-%02d-%02d %02d:%02d:%02d\n",++line,tp->tm_year+1900,tp->tm_mon+1,tp->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec);
                fflush(fp);
                sleep(1);
        }
        return 0;
}
相关推荐
chenzhou__1 小时前
LinuxC语言文件i/o笔记(第十八天)
linux·c语言·笔记·学习
简鹿办公2 小时前
重大更新!Ubuntu Pro 现提供长达 15 年的安全支持
linux·安全·ubuntu
01100001乄夵2 小时前
FPGA模块架构设计完全入门指南
经验分享·笔记·学习方法·fpga入门·fpga学习之路
01100001乄夵2 小时前
FPGA零基础入门:Verilog语法攻略
经验分享·笔记·学习方法·fpga入门·fpga学习之路
Nuyoah11klay2 小时前
华清远见25072班单片机高级学习day1
单片机·嵌入式硬件·学习
qq_321665332 小时前
验证centos 服务器(或其他linux服务器),443或80端口是否开通
linux·服务器·centos
java_logo2 小时前
TOMCAT Docker 容器化部署指南
java·linux·运维·docker·容器·tomcat
受之以蒙2 小时前
Rust ndarray 高性能计算:从元素操作到矩阵运算的优化实践
人工智能·笔记·rust
whb2341741242 小时前
测试linux删除Oracle文件,使用文件句柄恢复
linux·运维·oracle