Linux应用软件编程---文件操作2(fgets与gets的比较、fread/fwrite、流定位相关接口)
一、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】
更多推荐
所有评论(0)