C 知识点(5)

来源:互联网 发布:神反转的故事知乎 编辑:程序博客网 时间:2024/06/04 18:24

记录关于输入输出流和文件类型的相关知识点

文件的类型

大家都知道计算机的存储,物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有 ASCII 编码,二进制文件是基于值编码
的文件。
* 文本文件:
以 ASCII 码格式存放,一个字节存放一个字符。 文本文件的每一个字节存放一个 ASCII 码,代表一个字符。这便于对字符的逐个处理,但占用存储空间
较多,而且要花费转换时间。
* 二进制文件:
以值(补码)编码格式存放。二进制文件是把数据以二进制数的格式存放在文件中的,其占用存储空间较少。 数据按其内存中的存储形式原样存放。

实例

接下来通过一个例子说明两者的区别:
short int 型的变量在内存中占2个字节(8位)。

short int a = 10000;

数字10000的二进制表示是 ‭0010 0111 0001 0000十六进制表示为0x2710‬。
也就是说在计算机内存中变量a的值是以0x2710表示的,也就是之前说的二进制文件。
接下来通过输出到文本中,验证之前的表述。

#include <stdio.h>int main(){    short a = 10000;    FILE * fp = fopen("ascii.txt","w");    fprintf(fp,"%d",a);    fclose(fp);    FILE * fp2 = fopen("bin.txt","w");    fwrite(&a,2,1,fp2);    fclose(fp2);    return 0;}

分别以文本和二进制的形式输出到ascii.txtbin.txt文件中。以十六进制格式查看。

// ascii.txt31 30 30 30 30        ;10000

在文本输出中,分别以ASCII码的形式表示了1 0 0 0 0这5个数字。

// bin.txt10 27       ;

在二进制输出中,把内存中的储存形式直接输出到了txt文件中。


C语言中文件的输入输出

用到的函数和结构体

FILE 结构体

FILE 结构体是对缓冲区和文件读写状态的记录者,所有对文件的操作,都是通过
FILE 结构体完成的。

fopen 函数

以 Mode 的方式,打开一个 filename 命名的文件,返回一个指向该文件缓冲的 FILE 结构体指针。

Mode

Mode 处理方式 当文件不存在 当文件存在时 向文件输入 从文件输出 “r” 读取 出错 打开文件 不能 可以 “w” 写入 建立新文件 覆盖原有文件 可以 不能 “a” 追加 建立新文件 追加 可以 不能 “r+” 读取\写入 出错 打开文件 可以 可以 “w+” 写入\读取 建立新文件 覆盖原有文件 可以 可以 “a+” 读取\追加 建立新文件 追加 可以 可以

fclose 函数

fclose()用来关闭先前 fopen()打开的文件. 此动作会让缓冲区内的数据写入文件中, 并释放系统所提供的文件资源.

单字符读写

fputc 函数

将 ch 字符,写入文件。

#include <stdio.h>int main(){    FILE* fp = fopen("ascii.txt","w");    if(fp == NULL)    {        printf("open error\n");        return -1;    }    for(char ch = 'A';ch<='Z';ch++)    {        fputc(ch,fp);    }    fclose(fp);    return 0;}

fgetc 函数

从文件流中读取一个字符并返回。

#include <stdio.h>int main(){    FILE * fp = fopen("ascii.txt","r");    if(fp == NULL)    {        printf("open error\n");        return -1;    }    char ch;    while((ch = fgetc(fp))!=EOF)        printf("%2c",ch);    fclose(fp);    return 0;}

读取字符,重点是判断。

在C语言中,或更精确地说成C标准函数库中表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。

feof 这个函数,是去读标志位判断文件是否结束的。即在读到文件结尾的时候 再去读一次,标志位才会置位,此时再来作判断文件处理结束状态,文件到结尾。如果用于打印,则会出现多打一次的的现象。所以普遍这样使用:

#include <stdio.h>int main(){    FILE * fp = fopen ("ascii.txt","w+");    if(fp == NULL)    {        printf("open erroe\n");        return -1;    }    for (char ch = 'a';ch<='z';ch++)    {        fputc(ch,fp);    }    rewind(fp);    char ch;    while ((ch = fgetc(fp))&& !feof(fp)) {        printf("%3c",ch);    }    fclose (fp);    return 0;}

即先读,判断标志位。因为读到末尾也可能会让标志位置位,进而跳出循环。


文本操作 (一次读一行)

fputs 函数

把 str 指向的字符串写入 fp 指向的文件中。

#include <stdio.h>int main(){    FILE * fp = fopen ("ascii2.txt","w");    if(fp == NULL)    {        printf("open erroe\n");        return -1;    }    fputs("abcdefghijk\n",fp);    fputs("123456789\n",fp);    char buf[] = "xyz";    fputs(buf,fp);    fclose(fp);    return 0;}

fputs 函数

从 fp 所指向的文件中,至多读 length-1 个字符,送入字符数组 str 中,如果在读入 length-1 个字符结束前遇\n 或 EOF,读入即结束,字符串读入后在最后加一个‘\0’字符。

fgets 函数返回有三个条件:
1. 读 n-1 个字符前遇到\n,读取结束。
2. 读 n-1 个字符前遇到 EOF,读取结束。
3. 最多读 n-1 个符,在每读一行后自动追加’\0’。

#include <stdio.h>int main(){    FILE * fp = fopen ("ascii2.txt","r");    if(fp == NULL)    {        printf("open erroe\n");        return -1;    }    char buf[1024];    while (fgets(buf,1024,fp) != NULL)    {        printf("%s",buf);    }    fclose(fp);    return 0;}

二进制操作 (一次读写一块字符)

fwrite 函数

把 buffer 指向的数据写入 fp 指向的文件中

#include <stdio.h>#include <string.h>int main(){    FILE * fpw = fopen ("bin.txt","wb");    if(fpw == NULL)        return -1;    char * p = "china\nis\ngreat";    fwrite(p,1,strlen(p),fpw);    fclose(fpw);    return 0;}

输出结果

chinaisgreat

可以看出,不同于文本写入,二进制写入可吧特殊符号如\n写入。

fread 函数

把 fp 指向的文件中的 数据读到 buffer 中

#include <stdio.h>#include <string.h>int main(){    FILE * fpr = fopen ("bin.txt","rb");    if(fpr == NULL)        return -1;    char buf[1024];    int n;    n = fread(buf,1,1024,fpr);    printf("n =%d\n",n);    for(int i = 0;i<n;i++)    {        printf("%#x\t",buf[i]);    }    fclose(fpr);    return 0;}

运行结果

0x63    0x68    0x69    0x6e    0x61    0xa 0x69    0x73    0xa 0x67    0x72    0x65    0x61    0x74

其中文本格式中的回车\n,以0x0a读回。此时的回车符号被当做一个普通的
数据。

fread/fwrite 函数的输入返回参数

函数声明如下

int fwrite (void *buffer , int num_bytes , int count , FILE *pf)int fread (void *buffer , int num_bytes , int count , FILE *pf)
参数 含义 buffer 指向要输入/输出数据存储区的首地址的指针 num_bytes 每个要读/写的字段的字节数 count 要读/写的字段的个数 pf 要读/写的文件指针

num_bytes和count两个参数控制的是读写内容的大小。也就是读10个字节的内容,
num_bytes=2count=5num_bytes=5count=2两组参数的效果在读取内容上是相同的但是考虑到返回参数的含义,我们通常以读写内容的最小单位设定num_bytes的值。应为返回参数有如下定义:成功,返回读/写的字段数;出错或文件结束,返回 0。如果num_bytes的值与实际的读写单位大小不同,会造成返回值无意义或者无法通过返回值判断读写情况。


文件指针移动函数

  • rewind : 将文件指针重新指向一个流的开头。
  • ftell : 得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件 头部的字节数。
  • fseek : 偏移文件指针。
原创粉丝点击