C语言学习第015课——文件操作(二)
程序员文章站
2022-03-09 16:15:43
...
上一篇博文最后的内容,使用1024字节 也就是1KB的缓冲区,
去拷贝了20M的文件,循环次数有点多,可以通过修改SIZE的值,改成1024*1024或者8*1024*1024也就是8M,循环次数就小多了
遇到大文件,就用8M的缓冲区,遇到小文件就用1KB的缓冲区就行
那么如何获取到文件的大小呢?
获取文件状态
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
功能:获取文件状态信息
参数:
path:文件名
buf:保存文件信息的结构体
返回值:
成功:0
失败-1
struct stat {
dev_t st_dev; 文件的设备编号
ino_t st_ino; 节点
mode_t st_mode; 文件的类型和存取的权限
nlink_t st_nlink; 连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; 用户ID
gid_t st_gid; 组ID
dev_t st_rdev; (设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; 文件字节数(文件大小)
unsigned long st_blksize; 块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; 块数
time_t st_atime; 最后一次访问时间
time_t st_mtime; 最后一次修改时间
time_t st_ctime; 最后一次改变时间(指属性)
};
我们需要使用到的是st_size,简单的使用一下stat函数
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(void){
struct stat st;
stat("hello.txt",&st);
printf("%d\n",(int)st.st_size);
}
运行结果:
将stat函数使用到文件拷贝中,如果文件大于8M,就开辟8M的缓冲区进行拷贝,如果文件小于8M,就开辟文件大小的缓冲区进行拷贝
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#define SIZE 8*1024*1024
int main(int argc,char* argv[]){
FILE* fp1 = fopen(argv[1],"rb");
FILE* fp2 = fopen(argv[2],"wb");
if(!fp1 || !fp2){
printf("操作失败\n");
return -1;
}
if(argc<3){
printf("缺少参数\n");
return -2;
}
//开始读写
struct stat st; 获取文件状态,放入到st结构体中
stat(argv[1],&st);
char* ptemp = NULL;
int size = 0;
if(st.st_size>SIZE){ 根据文件大小,分配不同大小的内存空间
ptemp = (char*)malloc(sizeof(char)*SIZE);
size = SIZE; 不同大小的内存空间相应的函数参数也会发生改变
}else{
ptemp = (char*)malloc(sizeof(char)*st.st_size+10);
size = st.st_size+10; 小文件多预留10个字节的缓冲区,为了安全起见
}
printf("开辟的缓冲区大小为%d字节\n",size);
int count = 0;
while(!feof(fp1)){
memset(ptemp,0,size);
count = fread(ptemp,1,size,fp1);
fwrite(ptemp,1,count,fp2);
}
free(ptemp);
fclose(fp1);
fclose(fp2);
printf("拷贝成功\n");
return 0;
}
执行命令
运行结果
文件的随机读写
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
功能:移动文件流(文件光标)的读写位置。
参数:
stream:已经打开的文件指针
offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。
whence:其取值如下:
SEEK_SET:从文件开头移动offset个字节
SEEK_CUR:从当前位置移动offset个字节
SEEK_END:从文件末尾移动offset个字节
返回值:
成功:0
失败:-1
以下代码,是使用fgets读取文本文件两行数据
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
FILE* fp = fopen("hello.txt","r");
char str[30];
memset(str,0,30);
fgets(str,30,fp);
printf("%s",str);
memset(str,0,30);
fgets(str,30,fp);
printf("%s",str);
return 0;
}
现在想读完第二行之后,再读一次第二行,使用fseek函数实现,
我们知道,fseek函数是给光标进行偏移的,第二行内容“打不过我吧”5个汉字加一个\r和\n(Windows平台下的文件换行都是\r\n,Linux不是)
总共就是12个字节,所以使用fseek函数,先从当前位置往前偏移上12个字节试试
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
FILE* fp = fopen("hello.txt","r");
char str[30];
memset(str,0,30);
fgets(str,30,fp);
printf("%s",str);
memset(str,0,30);
fgets(str,30,fp);
printf("%s",str);
fseek(fp,-12,SEEK_CUR); 从当前光标位置,向左偏移12个字节 向右偏移时 使用正数
memset(str,0,30);
fgets(str,30,fp);
printf("%s",str);
return 0;
}
运行结果:
上一篇: ckeditor默认字体设置
下一篇: 工厂方法模式---实例
推荐阅读
-
操作系统: 二级目录文件系统的实现(c/c++语言)
-
一起talk C栗子吧(第一百三十九回:C语言实例--文件操作:基于文件描述符二)
-
一起talk C栗子吧(第一百四十二回:C语言实例--文件操作:基于文件指针二)
-
总结文件操作函数(二)-C语言
-
C++学习(二十八)(C语言部分)之 文件操作
-
一起talk C栗子吧(第一百三十九回:C语言实例--文件操作:基于文件描述符二)
-
C语言学习——文件——二进制读写
-
C语言学习第012课——内存管理和内存操作函数
-
C语言学习3-sprintf /system /文本和二进制文件 /进程退出 /typedef
-
一起talk C栗子吧(第一百四十二回:C语言实例--文件操作:基于文件指针二)