一、Linux操作系统默认打开的三个文件

        FILE * --->stdin:标准输入流 --->标准输入设备 (eg. 键盘)
        FILE * --->stdout:标准输出流-->标准输出设备 (eg. 显示屏)
        FILE * ---> stderr:标准出错流--->标准出错设备 (eg. 显示屏)

        都是 FILE * 文件流指针型。

二、标准IO读/写操作(续)

1、fgets与gets的对比

        1)fgets:

        (1)从指定的已打开文件中读取最多一行数据(遇到\n停止读取)
        (2)fgets保留\n字符并字符串末尾添加\0
        (3)fgets最多读取size-1个字符,最后一个位置存放\0

        2)gets

        (1)指定从终端设备读取数据
        (2)gets会将终端读到的\n字符替换成\0;
        (3)gets是危险的,因为在读取时,没有大小的限制,可能造成内存越界。

2、fread / fwrite

        fread/fwrite 读写操作,用来读写固定大小的二进制数据 (结构体) 、文本文件 (特殊的二进制文件) 。

        1)fread

        size_t fread(void *ptr, size_t size,,size_t nmemb, FILE *stream);
        功能:从文件中读取nmemb个大小是size的元素
        参数:
                ptr:存储读取到数据的首地址
                size:每个元素的大小
                nmemb:希望从文件中读取的元素个数
                stream:要读的文件流指针
        返回值:
                成功:实际读到的元素个数
                读到文件末尾:0

        2)fwrite

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

        功能:向文件中写入nmemb个大小是size的数据到文件中
        参数:
                ptr : 要写入的数据的首地址
               size:每个元素的字节数
               nmemb:要写入的元素个数
               stream:要写入的文件流指针
        返回值:
              成功:返回实际写入的元素个数

        3)例题

        读取一个bmp文件的头部,打印该bmp文件的分辨率和像素深度。(bmp(bitmap):位图,未压缩的图像格式,其存放信息结构如下图,前14个字节存放文件相关信息,中间40个字节存放图片相关信息,剩余部分存放颜色值)

        (1)构建结构体和函数
#pragma pack(1)//一下内容1字节运行

//bmp文件相关信息
typedef struct tagBITMAPFILEHEADER {
    short    bfType;         // 文件类型标志
    int      bfSize;         // 文件大小,单位为字节
    short    bfReserved1;    // 保留字节
    short    bfReserved2;    // 保留字节
    int      bfOffBits;      // 数据偏移量,即实际图像数据开始的位置
}Bmp_file_head_t;
//bmp图像信息
typedef struct tagBITMAPINFOHEADER {
    int   biSize;         // BITMAPINFOHEADER的大小,单位为字节
    int    biWidth;        // 位图的宽度,单位为像素
    int    biHeight;       // 位图的高度,单位为像素
    short    biPlanes;       // 目标设备的位平面数,必须为1
    short    biBitCount;     // 每像素位数(颜色深度)
    int   biCompression;  // 图像压缩类型
    int   biSizeImage;    // 图像大小,单位为字节
    int    biXPelsPerMeter;// 水平分辨率,单位为像素/米
    int    biYPelsPerMeter;// 垂直分辨率,单位为像素/米
    int   biClrUsed;      // 实际使用颜色数
    int   biClrImportant; // 重要颜色数
}Bmp_info_t;

#pragma pack() //结束1字节运行
int get_bmp_head_info(const char *bmpname, Bmp_file_head_t *pheadinfo, Bmp_info_t *pbmpinfo)
{
	FILE *fp = fopen(bmpname, "r");
	if (NULL == fp)
	{
		printf("fopen error\n");
		return -1;
	}
	fread(pheadinfo, sizeof(Bmp_file_head_t), 1, fp);
	fread(pbmpinfo, sizeof(Bmp_info_t), 1, fp);

	fclose(f);
	return 0;
}
        (2)主函数中书写格式
#include <stdio.h>

int main(int argc, const char *argv[])
{

	Bmp_file_head_t headinfo;
	Bmp_info_t bmpinfo;
	
	get_bmp_head_info("./01.bmp", &headinfo, &bmpinfo);

	printf("sizeof(Bmp_file_head_t) = %ld\n", sizeof(Bmp_file_head_t));
	printf("sizeof(Bmp_info_t) = %ld\n", sizeof(Bmp_info_t));
	printf("biWidth = %d, biHeight = %d, biBitCount = %d\n", bmpinfo.biWidth, bmpinfo.biHeight, bmpinfo.biBitCount);

	return 0;
}
        (3)运行结果

三、标准IO中的流定位相关接口

1、fseek(偏移)

        int fseek(FILE *stream, long offset, int whence);
        功能:实现文件流的重新定位
        参数:
                stream:需要定位的文件流指针
                offset:偏移量 
                whence:定位的相对位置
                         SEEK_SET : 从头进行偏移(此时,偏移量 offset 只能是正数)
                         SEET_CUR:从当前位置开始偏移(此时,偏移量 offset 可正可负)
                         SEET_END: 从文件末尾偏移(此时,偏移量 offset 可正可负)
        返回值:
              成功:返回当前的偏移量
              失败:-1

2、ftell(偏移量)

        long ftell(FILE *stream);
        功能:获取流的当前位置到文开头的偏移量
        参数:
                 stream:文件流
        返回:
               偏移量:byte

3、rewind(复位)

        void rewind(FILE *stream);
        功能:流复位函数(复位到开头)

4、例题

        eg1. 文件偏移量大小计算

        获取文件的大小(字节数),即文件的偏移量大小。

#include <stdio.h>

int main(void)
{
    FILE *fp = fopen("./1.txt", "w");
    if (NULL == fp)
    {
        printf("fopen error!\n");
        return -1;
    }
//偏移
    fseek(fp, 10, SEEK_SET);
    fputc('A', fp);

    fseek(fp, 5, SEEK_CUR);
    fputc('B', fp);

    fseek(fp, -2, SEEK_CUR);
    fputc('C', fp);

    fseek(fp, 4, SEEK_END);
    fputc('D', fp);

    fseek(fp, -10, SEEK_END);
    fputc('E', fp);
//计算
    fseek(fp, 0, SEEK_END);
    long t = ftell(fp);
    printf("占%ld byte\n", t);
    rewind(fp);

    fclose(fp);
}

        eg2. 模拟迅雷下载

        产生一个空洞文件 (无有效数据,只是占磁盘空间) 抢占磁盘空间,模拟迅雷下载。

         步骤     a. 获取源文件大小
                     b. 抢占目标文件的磁盘空间
                     c. 将数据拷贝到目标磁盘对应的位置(fread/fwrite实现文件拷贝)

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        printf("Usage:./a.out <srcfile> <dstfile>\n");
        return -1;
    }

    FILE *srcfile = fopen(argv[1], "r");
    if(NULL == srcfile)
    {
        printf("fopen srcfile error!\n");
        return -1;
    }
    //1、获取源文件大小
    fseek(srcfile, 0, SEEK_END);
    long len = ftell(srcfile);
    rewind(srcfile);

    //2、抢占目标文件的磁盘空间
    FILE *dstfile = fopen(argv[2], "w");
    if(NULL == dstfile)
    {
        printf("fopen dstfile error!\n");
        return -1;
    }

    fseek(dstfile, len-1, SEEK_SET);
    int ret = fputc('\0', dstfile);
    rewind(dstfile);
    if(EOF == ret)
    {
        printf("磁盘空间不足\n");
    } 

    //3、数据拷贝
    char buff[1024] = {0};
    while(1)
    {
        size_t cnt = fread(buff, 1, sizeof(buff), srcfile);
        if(cnt <= 0)
        {
            break;
        }
        fwrite(buff, 1, sizeof(buff), dstfile);
    }
    fclose(srcfile);
    fclose(dstfile);
    return 0;

        eg3. 查找单词注释

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
    char line[1024];
    int found = 0;

    FILE *fp = fopen("./dict.txt","r");
    if(fp == NULL)
    {
        printf("fopen error!\n");
        return -1;
    }
    while(1)
    {
    char i;
    printf("请输入单词:");
    char t[100];
    gets(t);
    if(strcmp(t, ".quit") == 0)
        {
            break;
        }
 
        int j = 0;
        char ss[1024] = {0};
        fgets(ss, 1024, fp);

        while(fgets(ss, 1024, fp) != 0)
        {
            if(strncmp(ss, t, strlen(t)) == 0)
            {
                char *p = strtok(ss, " ");
                p = strtok(NULL, "\r");
                puts(p);
                break;
            }
            fgets(ss, 1024, fp);
        }
        rewind(fp);
    }

    fclose(fp);
    return 0;
}

【END】        

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐