C语言中文件定位函数主要是:fseek, ftell, fsetpos, fgetpos。

先来讲前两个函数,这是最基本的定位函数:


  fseek函数:能把文件指针移动到文件任何位置,其原型是:int fseek(FILE *fp, long offset, int fromwhere);

  参数解释:第一个参数为要进行定位的文件的指针;第二个参数为定位的偏移量,一个有符号的long类型值,正数表示文件指针向后偏移,负数表示文件指针向前偏移,0 表示不进行偏移;第三个参数表示文件指针从哪个位置开始偏移,有三个值可选,SEEK_SET & SEEK_CUR & SEEK_END,分别表示文件第一个字节(即第零个位置),文件指针当前所指字节(即当前位置)和文件EOF位置。

  返回值:返回 0 表示操作成功,返回非 0 表示操作失败。

  其他注意:该函数不能定位到第一个字节之前的位置,如果尝试这样操作会导致fseek返回 -1,即操作失败,比如这样的代码“j = fseek(fp, -4L, SEEK_SET );”,其中 j 值就是 -1;但是,该函数能定位到EOF位置之后的位置,并且不报错,即使这样是没有意义的,比如这样的代码“j = fseek(fp, 4L, SEEK_END)”,返回值 j 是 0,并且此时 ftell(fp) 返回值是SEEK_END + 4。


  ftell函数:能返回当前文件指针所在的位置(文件的第一个字节所在位置是零),其原型是:long ftell(FILE *fp);

  参数解释:有且仅有一个参数,为一个文件的指针。

  返回值:有符号long类型的正向值,即0~2147483647。

  其他注意:暂无。


实际上,前两个函数对文件指针的定位虽然都很方便,但是它们都有一个局限性,那就是它们能定位的最大字节是依据 long 类型的取值范围决定。比如 fseek(fp, max_pos, SEEK_SET);,它能移动的最大偏移量是 max_pos = 2147483647字节,即1GB,对于大于1GB的文件来说就力不从心了。

所以ANSI C推出了解决大文件定位的方案,即后两个函数!(不过,即使是现在,直接处理一个超过1G的单文件还是比较少的)

在说这两个函数之前,先要介绍一个数据类型fpos_t,它是一个结构体类型,保存着文件指针的位置,并且这种数据类型只能被fgetpos和fsetpos函数使用。


  fsetpos函数:将文件指针的位置设置为fpos_t类型变量所保存的位置,其原型是:int fsetpos(FILE *, const fpos_t *)

  参数解释:第一个参数为一个文件的指针;第二个参数为一个fpos_t类型的指针。

  返回值:0 表示操作成功,非 0 表示操作失败。

  其他注意:暂无。


  fgetpos函数:将文件指针的位置保存到fpos_t类型变量中,其原型是:int fgetpos(FILE *, fpos_t *)

  参数解释:同fsetpos。

  返回值:同fsetpos。

  其他注意:暂无。


总结:后两个函数通常是fseek函数偏移累加之后超过long范围时才用到,例如如下代码:

fpos_t pos;
//定义一个fpos_t类型的变量pos
f = fopen("a.txt", "r");
//假设a.txt是一个超过1G的文件
fseek(f, 2000000000L, SEEK_SET);
//向后偏移20亿字节
fseek(f, 1000000000L, SEEK_CUR);
//再向后面偏移10亿字节
//此时,文件指针的位置已经超过了signed long的正向范围,就需要用fpos_t类型变量来保存文件指针位置了
fgetpos(f, &pos);
//此时,当前文件指针的位置已保存到pos变量中了
fseek(f, 5000L, SEEK_CUR);
printf("%x\n", getc(f));
//再向后偏移5千字节,并取出偏移后所在的字节,以十六进制打印出来
fsetpos(f, &pos);
//利用fsetpos函数重置文件指针,根据最后一次fgetpos保存的pos值,这次函数操作将向前偏移5千字节
printf("%x\n", getc(f));
//以十六进制打印出当前字节
fclose(f);
//释放文件流

上述代码可能有点抽象,因为你可能一时间找不到大于1G的文件,那么我们就用小文件来演示一下:

假设文件"utf8.txt"的十六进制结构如下:

41 42 43 56 57 44 44 4B

C语言代码如下:

FILE * f1;
fpos_t pos;
f1 = fopen("utf8.txt", "r");
fseek(f1,,SEEK_SET);
fgetpos(f1, &pos);
fseek(f1,,SEEK_SET);
printf("%x\n", getc(f1));
fsetpos(f1,&pos);
printf("%x\n", getc(f1));
fclose(f1);

输出结果:

57
43
Press any key to continue

C语言中文件定位函数总结的更多相关文章

  1. 如何在C语言中调用Swift函数

    在Apple官方的<Using Swift with Cocoa and Objectgive-C>一书中详细地介绍了如何在Objective-C中使用Swift的类以及如何在Swift中 ...

  2. C语言中变量和函数的作用域和链接属性

    C语言中变量和函数的作用域和链接属性 作用域 代码块作用域: 代码块指的是使用"{}"包围起来的部分. 在代码块中定义的变量,代码块之外是不能访问的. 代码块嵌套之后的变量作用域, ...

  3. C语言中的自定义函数

    C语言中可以使用系统函数也可以使用自己的函数,就是自定义函数 自定义函数分为四种 第一种:无参无返回值的 函数的声明 void sayH(); 函数的实现 void sayH(){ printf(&q ...

  4. C语言中返回字符串函数的四种实现方法 2015-05-17 15:00 23人阅读 评论(0) 收藏

    C语言中返回字符串函数的四种实现方法 分类: UNIX/LINUX C/C++ 2010-12-29 02:54 11954人阅读 评论(1) 收藏 举报 语言func存储 有四种方式: 1.使用堆空 ...

  5. 查看Linux下*.a库文件中文件、函数、变量

    查看Linux下*.a库文件中文件.函数.变量等情况在Linux 下经常需要链接一些 *.a的库文件,那怎么查看这些*.a 中包 含哪些文件.函数.变量: 1. 查看文件:ar -t xxx.a 2. ...

  6. C语言中返回字符串函数的四种实现方法

    转自C语言中返回字符串函数的四种实现方法 其实就是要返回一个有效的指针,尾部变量退出后就无效了. 有四种方式: 1.使用堆空间,返回申请的堆地址,注意释放 2.函数参数传递指针,返回该指针 3.返回函 ...

  7. C语言中关于scanf函数的用法

    scanf()函数的控制串 函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化 ...

  8. python 和 R 语言 中的 range() 函数

    1.python 中的 range() 函数生成整数序列,常用于 for 循环的迭代. 示例: 2.R 语言中的 range() 函数返回一个数值向量中的最小值和最大中,常用于求极差. 示例: 按语: ...

  9. C语言中的回调函数(Callback Function)

    1 定义和使用场合 回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数.函数是你实现 ...

随机推荐

  1. levelDB数据库使用及实例 - 高性能nosql存储数据库

    LevelDB是google公司开发出来的一款 超高性能kv存储引擎,以其惊人的读性能和更加惊人的写性能在轻量级nosql数据库中鹤立鸡群. 此开源项目目前是支持处理十亿级别规模Key-Value型数 ...

  2. todo reading

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind https ...

  3. SQL的类型转换

    说到SQL类型转换,我们知道SQL是一个弱类型语言,所以可以做隐式的强制类型转换,下面记录一下这几天遇到的类型转换问题. 1.在SQL中,字符串类型与数字之间转换是不需要强制类型转换符的,如果字符串是 ...

  4. VS2008中C++打开Excel(MFC)

    VS2008中C++打开Excel(MFC)——摘自网络,并加以细化 第一步:建立project(新建项目) 英文版 中文版 选择C++下的MFC Application(基于对话框的项目) 英文版 ...

  5. 【深入理解Java虚拟机】自动内存管理机制——垃圾回收机制

      Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...

  6. 基于BootStrap,FortAweSome,Ajax的学生管理系统

    一. 基于BootStrap,FortAweSome,Ajax的学生管理系统代码部分 1.students.html <1>html页面文件 <!DOCTYPE html> & ...

  7. 3.1、Ansible命令简要说明及初步使用

    1.Ansible命令 1.1 Ad-hoc说明 Ansible中有一个很重要的功能就是可以执行ad-hoc命令,它表示即时.临时的意思,即表示一次性的命令.与之相对的是ansible playboo ...

  8. Python 纸牌游戏

    纸牌游戏 # card.py from random import shuffle class Card: # 黑桃,红桃,方块,梅花 suits = ['spades', 'hearts', 'di ...

  9. vue 如何清除定时器

    在页面中需要定时刷新局部数据,在数据变化是否频繁的情况下,没有必要使用webSocket,因为数据变化频繁,数据实时变化太快看不清楚.因此页面会定时调用后台接口以达到实时刷新数据的效果. 1.在dat ...

  10. 【Manthan, Codefest 18 (rated, Div. 1 + Div. 2) C】Equalize

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] Swap操作显然只能对(i-1,i)执行才有用. 不然直接将i翻转以及j翻转 显然比直接交换更优. 那么现在我们就相当于有两种操作. ...