C 知识点(5)

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

文件的类型

大家都知道计算机的存储,物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有 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.txt
31 30 30 30 30        ;10000

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

// bin.txt
10 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;
}

输出结果

china
is
great

可以看出,不同于文本写入,二进制写入可吧特殊符号如\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 : 偏移文件指针。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值