1.fseek()
int fseek(FILE *stream,long offset,int whence);
返回值 成功返回0,失败返回-1
long offset 偏移量 向前偏移,向后偏移。
int whence SEEK_CUR (文件当前位置)SEEK_SET(文件首) SEEK_END(文件尾)
fp=fopen(); //先打开文件,然后放入10个字符在读10个字符,不会读到这是个字符。
fputc(fp)*10; //你放入的10个字符
fgetc();*10//不会读到你放入的十个字符,因为文件当中有一个文件位置指针,文件位置指针目前的位置称为当前位置,你的读和写都是发生在当前位置的。
fd=fopen();
fputc()*10;
fclose();
fopen();
fgetc();这样就可以读出来你写入的十个字符。
fopen();
fputc()*10;
fseek(,-10L,SEEK_CUR);
fgetc()*10;
long tell(FILE *stream);
告诉文件位置指针在哪里
可以查看文件大小
fseek(,0,SEET_END);
ftell();
void rewind(FILE *stream);
相当于void fseek(stream,0L,SEEK_SET);
#include "stdio.h"
#include "stdlib.h"
int main(int argc,char **argv)
{
if(argc<2)
{
fprintf(stderr,"Usage:%s <srcfile> <destfile>",argv[0]);
}
FILE * fp;
fp=fopen(argv[1],"r+");
if(fp==NULL)
{
perror("fopen()");
exit(1);
}
long whence= ftell(fp);
printf("文件位置在: %ld \n",whence);
fseek(fp,0,SEEK_END);
whence =ftell(fp);
printf("文件位置在:%ld \n",whence);
fclose(fp);
exit(0);
}
fseek可以用来生成空洞文件。
字符ASCII码为0的特殊字符,\0,并不是'\0'
文件全部或者一部分充斥着\0叫做空洞文件
建立下载任务是,开始下载时,在你的磁盘上产生一个文件,那个文件到底是从一个字节涨到文件大小的字节呢?还是那个文件直接就是文件大小呢?
基本上你下载文件产生那个不可识别图标的文件,一上来就时文件本身大小。因为他不能下载到一半告诉你空间不够,空洞文件就是你杠下载产生的文件,要它先占领磁盘的空间。
那么怎么占领呢?
你先touch一个文件,本身文件的大小为0,产生文件后调用fseek函数,将该文件从头部开始延伸,直接使文件文件成为文件本身大小,也就是一个空文件产生,直接将空文件用fseek拉到文件本身大小的空间,文件里面全是ASCII码为0的\0。然后下载。
一般的下载工具这样实现下载: 将所要下载的文件,切成片,用多进程或多线程进行下载(一般是多线程),多线程用来进行每一块的下载,每个线程锁定自己的一块文件进行下载,其他线程不能对这一块文件读写。否则会引起竞争和冲突。
fseek(FILE *stream,long offset,int whence);
long ftell(FILE * stream);
long 是有符号整型最多表示-2G~2G-1,但是在ftell返回值只能是0~2G-1,虽然fseek可以访问到4G-1大小文件内的所有数据,但是ftell最大就是2G-1,所以文件大小在ftel函数下只能为2G-1。但是在遇到一些大文件是就不能访问全部了。所以需要扩大范围。
int fseeko(FILE *stream,off_t,int whence);
off_t ftell(FILE *stream);
在某些体系结构当中,把off_t和long都是32位。有两种方法可以将32变成64位。①在头文件之前加入#define _FILE_OFFSET_BITS 64
②gcc a.c -D_FILE_OFFSET_BITS=64
2.缓冲区
现在有一个程序,
1 #include "stdio.h"
2 #include "stdlib.h"
3 int main()
4 {
5 printf("before while()");
6 while(1);
7 printf("after while()");
8 exit(0);
9 }
~
~
现在来猜一下结果是什么,结果是什么也不会输出,
那么现在还有一个程序:
1 #include "stdio.h"
2 #include "stdlib.h"
3 int main()
4 {
5 // printf("before while()");
6 // while(1);
7 // printf("after while()");
8
9 printf("before while()\n");
10 while(1);
11 printf("after while()\n");
12 exit(0);
13 }
~
这段程序会输出before while()
还有一个程序
1 #include "stdio.h"
2 #include "stdlib.h"
3 int main()
4 {
5 // printf("before while()");
6 // while(1);
7 // printf("after while()");
8
9 // printf("before while()\n");
10 // while(1);
11 // printf("after while()\n");
12 printf("before\n");
13 printf("after\n");
14 exit(0);
15 }
~
这段程序输出的是before和after
还有一段程序
1 #include "stdio.h"
2 #include "stdlib.h"
3 int main()
4 {
5 // printf("before while()");
6 // while(1);
7 // printf("after while()");
8
9 // printf("before while()\n");
10 // while(1);
11 // printf("after while()\n");
12 // printf("before\n");
13 // printf("after\n");
14 printf("before");
15 printf("after");
16 exit(0);
17 }
这段程序输出的是before after
造成这种现象就是由于缓冲区的存在,缓冲区有三种刷新方式1.行刷新2.强制刷新3.满刷新
行缓冲,(标准输出就是行缓冲)当一行满了或者见到‘\n’时就会输出前面的内容。
全缓冲:就是满了的时候进行刷新(默认是全缓冲)。
无缓冲:如stderr这种,需要立即输出内容。
缓冲区在大多数情况下是好的,作用是合并系统调用。
进程结束也会对缓冲区进行刷新也就是最后一个程序没有行满也没有见到‘\n’为什么也能输出。
刷新函数。
int fflush(FILE * stream);
int fflush();
没有参数那该刷新的就会刷新。
#include "stdio.h"
2 #include "stdlib.h"
3 int main()
4 {
5 printf("before while");
6 while(1);
7 printf("after while()");
8 exit(0);
9 }
什么也不会输出。
1 #include "stdio.h"
2 #include "stdlib.h"
3 int main()
4 {
5 // printf("before while");
6 // while(1);
7 // printf("after while()");
8 printf("before while()");
9 fflush(stdout);
10 while(1);
11 printf("after while()");
12 fflush(NULL);
13 exit(0);
14 }
输出before while
可以使用setvbuf来修改刷新方式,一般不用。
int setvbuf(FILE * stream,char *buf,int mode,size_t size);