C&C++实现文件偏移操作的常用方法

一.标准c++文件流操作方式:

对输入流操作

seekg():设置输入文件流的文件流指针位置

tellg():返回当前定位指针的位置,也代表着输入流的大小。

对输出流操作

seekp():设置输出文件流的文件流指针位置

tellp():用于输入流,返回流中‘get’指针当前的位置

函数原型:

ostream& seekp( streampos pos );

ostream& seekp( streamoff off, ios::seek_dir dir );

istream& seekg( streampos pos );

istream& seekg( streamoff off, ios::seek_dir dir );

函数参数:

pos:新的文件流指针位置值,可以是正负数值,正的表示向后偏移,负的表示向前偏移。

off:需要偏移的值

dir:搜索的起始位置

dir参数用于对文件流指针的定位操作上,代表搜索的起始位置。在ios中定义的枚举类型: enum seek_dir {beg, cur, end};每个枚举常量的含义:

ios::beg:文件流的起始位置

ios::cur:文件流的当前位置

I        os::end:文件流的结束位置

调用示例:

表 2 文件寻找操作

语 句

如何影响读/写位置

file.seekp(32L, ios::beg);

将写入位置设置为从文件开头开始的第 33 个字节(字节 32)

file.seekp(-10L, ios::end);

将写入位置设置为从文件末尾开始的第 11 个字节(字节 10)

file.seekp(120L, ios::cur);

将写入位置设置为从当前位置开始的第 121 个字节(字节 120)

file.seekg(2L, ios::beg);

将读取位置设置为从文件开头开始的第 3 个字节(字节 2)

file.seekg(-100L, ios::end);

将读取位置设置为从文件末尾开始的第 101 个字节(字节 100)

file.seekg(40L, ios::cur);

将读取位置设置为从当前位置开始的第 41 个字节(字节 40)

file.seekg(0L, ios:rend);

将读取位置设置为文件末尾

程序示例:

假设文件 letters.txt 中包含以下数据:

Byte 5 from beginning: f
Byte 10 from end: q
Byte 3 from current: u

下面的程序使用了 seekg 函数跳转到 letters.txt 文件中的不同位置,每次停止后都检索一个字符:

  1. //This program demonstrates the seekg function.
  2. #include <iostream>
  3. #include <fstream>
  4. using namespace std;
  5. int main()
  6. {
  7.     // Variable to access file
  8.     char ch;
  9.     // Open the file for reading
  10.     fstream file ("letters.txt", ios::in);
  11.     if (!file)
  12.     {
  13.         cout << "Error opening file.";
  14.         return 0;
  15.     }
  16.     // Get fifth byte from beginning of alphabet file
  17.     file.seekg(5L, ios::beg);
  18.     file.get(ch);
  19.     cout << "Byte 5 from beginning: " << ch << endl;
  20.     // Get tenth byte from end of alphabet file
  21.     file.seekg(-10L, ios::end);
  22.     file.get(ch);
  23.     cout << "Byte 10 from end: " << ch << endl;
  24.     //Go forward three bytes from current position
  25.     file.seekg(3L, ios::cur);
  26.     file.get(ch);
  27.     cout << "Byte 3 from current: " << ch << endl;
  28.     // Close file
  29.     file.close ();
  30.     return 0;
  31. }

程序输出结果:

Byte 5 from beginning: f
Byte 10 from end: q
Byte 3 from current: u

下面的程序显示了 seekg 函数的另一个例子。它打开了包含两个记录的 people.dat 文件。该程序首先显示记录 1(第二条记录),然后显示记录 0。

  1. // This program demonstrates the use of a structure
  2. // variable to read a record of information from a file.
  3. #include <iostream>
  4. #include <fstream>
  5. using namespace std;
  6. const int NAME_SIZE = 51, ADDR_SIZE = 51, PHONE_SIZE = 14;
  7. //声明记录的结构
  8. struct Info
  9. {
  10.     char name[NAME_SIZE];
  11.     int age;
  12.     char address1[ADDR_SIZE];
  13.     char address2[ADDR_SIZE];
  14.     char phone[PHONE_SIZE];
  15. };
  16. // Function Prototypes
  17. long byteNum(int);
  18. void showRec(Info);
  19. int main()
  20. {
  21.     // Person information
  22.     Info person;
  23.     // Create file object and open the file
  24.     fstream people("people.dat", ios::in | ios::binary);
  25.     if (!people)
  26.     {
  27.         cout << "Error opening file. Program aborting.\n"; return 0;
  28.     }
  29.     // Skip forward and read record 1 in the file
  30.     cout << "Here is record 1:\n";
  31.     people.seekg(byteNum(1), ios::beg);
  32.     people.read(reinterpret_cast<char *>(&person), sizeof (person));
  33.     showRec(person);
  34.     // Skip backwards and read record 0 in the file
  35.     cout << "\nHere is record 0:\n";
  36.     people.seekg(byteNum(0), ios::beg);
  37.     people.read(reinterpret_cast<char *>(&person), sizeof (person));
  38.     showRec(person);
  39.     // Close the file
  40.     people.close();
  41.     return 0;
  42. }
  43. long byteNum(int recNum)
  44. {
  45.     return sizeof (Info) * recNum;
  46. }
  47. void showRec(Info record)
  48. {
  49.     cout << "Name:";
  50.     cout << record.name << endl;
  51.     cout << "Age: ";
  52.     cout << record.age << endl;
  53.     cout << "Address line 1: ";
  54.     cout << record.address1 << endl;
  55.     cout << "Address line 2: ";
  56.     cout << record.address2 << endl;
  57.     cout << "Phone: ";
  58.     cout << record.phone << endl;
  59. }

程序屏幕输出结果:

Here is record 1:
Name:cyuyan
Age: 20
Address line 1: No.1
Address line 2: No.2
Phone: 12345678

Here is record 0:
Name:http://c.biancheng.net
Age: 5
Address line 1: No.1
Address line 2: No.2
Phone: 123456

该程序除了 main 以外还有两个重要的函数。第一个是 byteNum,它釆用一个记录编号作为实参,并返回该记录的起始字节。它通过将记录编号乘以 Info 结构的大小来计算记录的起始字节。这将从文件的开始处返回该记录的偏移量。第二个函数是 showRec,它接收一个 Info 结构作为实参,并在屏幕上显示其内容。

二. MFC CFile类调用

virtual ULONGLONG Seek( LONGLONG lOff, UINT nFrom );

参数:

 lOff 移動檔案指標的位元組數目。 正值會向上捲動到檔案結尾的檔案指標;負值會將會向檔案的起始檔案指標。

nFrom 要尋找的位置。 的可能值。

傳回值資料指標的位置,如果方法成功,否則,傳回值為未定義,並為 CFileException 例外狀況的指標會擲回。

 备注:

下表列出 nFrom 參數的可能值。

  CFile::begin 搜尋檔案開頭。

  CFile::current 從檔案指標的目前位置的搜尋。

  CFile::end 從檔案結尾的搜尋。

 在開啟檔案時,檔案指標放置在 0 中,檔案的開頭。 您可以將檔案指標至超出檔案尾端的位置。 如果您這樣做,檔案大小不增加,直到寫入檔案。 在例外狀況處理後,這個方法的例外處理常式必須刪除例外狀況物件。

  实例:

CFile cfile;

cfile.Open(_T("Seek_File.dat"), CFile::modeCreate | CFile::modeReadWrite);

LONGLONG lOffset = 1000;

ULONGLONG lActual;

lActual = cfile.Seek(lOffset, CFile::begin);

三 C标准库函数fseek()

C 库函数 int fseek(FILE *stream, long int offset, int whence) 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。

声明

下面是 fseek() 函数的声明。

int fseek(FILE *stream, long int offset, int whence)

参数

  • stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
  • offset -- 这是相对 whence 的偏移量,以字节为单位。
  • whence -- 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:

常量

描述

SEEK_SET

文件的开头

SEEK_CUR

文件指针的当前位置

SEEK_END

文件的末尾

返回值

如果成功,则该函数返回零,否则返回非零值。

实例

下面的实例演示了 fseek() 函数的用法。

#include <stdio.h>
int main ()
{
   FILE *fp;
   fp = fopen("file.txt","w+");
   fputs("This is runoob.com", Fp);
   fseek( fp, 7, SEEK_SET );
   fputs(" C Programming Langauge", fp);
   fclose(fp);
   return(0);
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

illdragon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值