1.stat文件
stat命令来源于linux,用于查看文件的具体存储信息
#include <sys/stat.h>//头文件
int stat(const char * path, struct stat * buf)
//把path路径下的文件,交给buf代理
stat.st_size;//文件大小,单位:字节
函数的第一个参数代表文件名,第二个参数是struct stat结构。
得到文件的属性,包括文件建立时间,文件大小等信息。
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
int main(){
struct stat st = {0};
stat("D:\\temp\\a.txt",&st);
printf("%ld",st.st_size);
return 0
}
2.fread和fwrite函数
这两个函数时用于读写一个二进制文件的,因为fputs和fgets是针对文本文件,而图像,音频等都是二进制文件,需要其他的读取方式
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
第一个参数是buf的内存地址
第二个参数是写多少个单位
第三个参数是每个单位的大小
第四个参数是fopen返回的文件指针
只要第二个参数和第三个参数乘积一样,和第一个参数所指的内存区域一样大就可以。
注意:这个函数以二进制形式对文件进行操作,不局限于文本文件
返回值:返回实际写入的数据块数目
当fread的第二个参数是1的时候,可以认为fread返回的值是读取到的字节数
----------------------------------------------------------------
int main(){//fwrite
int a = 100;
FILE *p = fopen("D:\\temp\\a.dat","wb");
//在windows读取二进制文件的时候都要加b,防止自动添加\r
fwrite(&a,1,sizeof(int),p);
//等价于
fwrite(&a,sizeof(int),1,p);
//也等价于
fwrite(&a,4,sizeof(char),p);
int array[10] = {1,2,3,4,5,6,7,8,9,10};
fwrite(array,1,sizeof(array),p);
/*
第一个参数是buf的内存地址
第二个参数是写多少个单位
第三个参数是每个单位的大小
第四个参数是fopen返回的文件指针
只要第二个参数和第三个参数乘积一样,和第一个参数所指的内存区域一样大就可以
*/
fclose(p);
return 0;
}
int main(){//fread
FILE *p = fopen("D:\\temp\\a.dat","rb");
while(!feof(p)){
int a;
if(fread(a,1,sizeof(a),p)==0)break;//解决多读最后一行的问题!
//int rec = fread(a,1,sizeof(a),p); //一个单位是1个字节,fread的返回值代表读取了多少个单位
// printf("rec = %d , a = %d\n",rec,a[i]);//输出rec = 4,代表返回了多少个单位
//假设
fread(buf,5,sizeof(int),p);//如果最后一次调用读取了3个int,那么返回0
}
fclose(p);
return 0;
}
3.拷贝二进制文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#pragma warning(disable:4996)
int main(){
FILE *p1 = fopen("D:\\temp\\a.dat","rb");//音频文件都可以拷贝
FILE *p2 = fopen("D:\\temp\\b.dat","wb");
if (p1 == NULL)
{
return 0;
}
if (p2 == NULL)
{
return 0;
}
/*
while(1)
{
int a;
if (fread(&a,1,sizeof(a),p1)==0)break;
//每一次只读1个单位,一个单位为4BYTE,造成的结果是文件大小总是4的倍数
//如果是exe的话就运行不了了
fwrite(&a,1,sizeof(a),p2);
}
下面改进===
*/
int index = 0;//计数器
while(1)
{
char buf[1024] = {0};
int rc = fread(buf,1,sizeof(buf),p1);//rc可以认为是从p1中读取到的字节数
if(rc==0)break;
fwrite(&buf,1,rc,p2);//不是4个为1单位,而是rc为1单位,有4就4,不够就少一点
index++;
}
printf("%d\n",index);
fclose(p1);
fclose(p2);
return 0;
}
==============================提高效率,利用堆和stat================================
int main(){//没有考虑到堆不够的情况
FILE *p1 = fopen("D:\\temp\\a.wmv","rb");
FILE *p2 = fopen("D:\\temp\\b.wmv","wb");
if (p1 == NULL)
{
return 0;
}
if (p2 == NULL)
{
return 0;
}
struct stat st = {0};
stat("D:\\temp\\a.wmv",&st);
char *buf = malloc(st.st_size);//文件多大,就分配多大的一个堆空间
//要注意堆内存不够的情况
fread(buf,1,st.st_size,p1);
fwrite(buf,1,st.st_size,p1);
fclose(p1);
fclose(p2);
free(buf);
return 0;
}
==============================终极版提高效率================================
#define MAX_MEM 1024 * 1024 * 4 //阀值设置为4M
int main(int argc, char *args[]){//假设文件巨大
if (argc < 3)
{
printf("参数不够\n");
return 0;
}
FILE *p1 = fopen(args[1],"rb");//输入不需要转意符
FILE *p2 = fopen(args[2],"wb");
if (p1 == NULL)
{
printf("打开%s失败\n",args[1] );
return 0;
}
if (p2 == NULL)
{
printf("打开%s失败\n",args[2] );
return 0;
}
//设置一个阀值,如果低于这个阀值的话,那么就分配实际大小
//如果高于这个阀值,那么就分配阀值的大小
struct stat st = {0};
stat(args[1],&st);
int max;
if(st.st_size<MAX_MEM)
{
max = st.st_size
}
else
{
max= MAX_MEM;
}
char *buf = malloc(max);//文件多大,就分配多大的一个堆空间
while(1)
{
int rc = fread(buf,1,max,p1);
if(rc == 0)break;
fwrite(buf,1,rc,p1);
}
fclose(p1);
fclose(p2);
free(buf);
return 0;
}
网友评论