嵌入式学习(Day24)fread/fwrite
1、fgets补充:
fgets:
(1)从指定的已打开文件中读取最多一行数据(遇\n停止读取)
(2)fgets保留\n字符并在字符串末尾添加\0
(3)fgets最多读取size-1个字符,最后一个位置存放\0
gets:
(1)指定从终端设备读取数据
(2)gets会将终端读到的\n字符替换成\0
(3)gets是危险的,因为在读取时,没有大小的限制,可能造成内存越界
2、Linux系统默认打开的三个文件:
FILE *-->stdin 标准输入流 ----》标准输入设备:键盘
FILE *-->stdout 标准输出流 ---》标准输出设备:显示屏
FILE *-->stderr 标准出错流 ---》标准出错流(用于输出错误信息) 标准出错设备:显示器
3、size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能: 向文件中写入 nmemb
个大小是 size
的数据到文件中。
参数:
ptr
:要写入的数据的首地址。size
:每个元素的字节数。nmemb
:要写入的元素个数。stream
:要写入的文件流指针。
返回值:
- 成功:返回实际写入的元素个数。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能: 从文件中读取 nmemb 个大小是 size 的元素。
参数:
ptr
:存储读取到数据的首地址。size
:每个元素的大小。nmemb
:希望从文件中读取的元素个数。stream
:要读的文件流指针。
返回值:
- 成功:实际读到的元素个数。
- 读到文件末尾:0。
例:读取一个bmp文件头部,打印该bmp文件分辨率和像素深度
#include <stdio.h>
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER
{short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件int bfsize; // 文件大小 以字节为单位(2-5字节)short bfReserved1; // 保留,必须设置为0 (6-7字节)short bfReserved2; // 保留,必须设置为0 (8-9字节)int bfoffBits; // 从文件头到像素数据的偏移 (10-13字节)
}Bmp_file_head_t;typedef struct tagBITMAPINFOHEADER
{int biSize; // 此结构体的大小 (14-17字节)int biWidth; // 图像的宽 (18-21字节)int biHeight; // 图像的高 (22-25字节)short biPlanes; // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节)short biBitCount; // 一像素所占的位数,一般为24 (28-29字节)int biCompression; // 说明图象数据压缩的类型,0为不压缩。 (30-33字节)int biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节)int biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节)int biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节)int biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节)int biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节)
}Bmp_info_t;#pragma pack()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(fp);return 0;
}int main(int argc, const char *argv[])
{Bmp_file_head_t headinfo;Bmp_info_t bmpinfo;get_bmp_head_info("./3.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;
}
4、流定位相关接口
(1)int fseek(FILE *stream, long offset, int whence);
功能: 实现文件流重新定位。
参数:
stream
:需要定位的文件流指针。offset
:偏移量。whence
:定位的相对位置:SEEK_SET
:从头进行偏移。SEEK_CUR
:从当前位置开始偏移。SEEK_END
:从文件末尾偏移。
返回值:
- 成功:返回当前的偏移量。
- 失败:
-1
。
(2)long ftell(FILE *stream);
功能: 获取流的当前位置到文件开头的偏移量。
参数:
stream
:文件流。
返回:
- 偏移量(以字节为单位)。
(3)void rewind(FILE *stream);
功能: 流复位函数(复位到开头)。
fseek(fp, 0, SEEK_SET);
例:模拟迅雷下载:
#include <stdio.h>
#include <stdlib.h>int main(int argc,const char *argv[])
{if(argc <3){printf("Usage: ./a.out <srcfile> <dstfile>");return -1;}FILE *fpsrc = fopen(argv[1],"r");if(NULL ==fpsrc){printf("fopen error\n");return -1;}//获取源文件大小fseek(fpsrc,0,SEEK_END);long len = ftell(fpsrc);rewind(fpsrc);//抢占目标文件磁盘空间FILE *fpdst = fopen(argv[2],"w");if(NULL == fpdst){printf("fopen error\n");return -1;}fseek(fpdst,len - 1,SEEK_SET);int ret = fputc('\0',fpdst);if(EOF == ret){printf("磁盘空间不足\n");fclose(fpsrc);fclose(fpdst);return -1;}rewind(fpdst);//复位//数据拷贝char *buff = malloc(len);fread(buff,len,1,fpsrc);fwrite(buff,len,1,fpdst);free(buff);fclose(fpsrc);fclose(fpdst);/*//3、数据拷贝char buff[1024] = {0};while (1){size_t cnt = fread(buff, 1, sizeof(buff), fpsrc);if (0 == cnt){break;}fwrite(buff, 1, cnt, fpdst);}fclose(fpsrc);fclose(fpdst); */return 0;
}