第七讲:c/c++文件的读取、操作和定位

来源:互联网 发布:讲课视频软件 编辑:程序博客网 时间:2024/05/21 06:39
本文的编写是为了在学习c++的时候加深自己的记忆,同时也为与我一般的初学者提供一些参考,此处特别感谢微信公众号“c/c++的编程教室”,我的学习过程按照公众号的推送进行学习的!

1.文件的读取

(1)打开文件一般采用fopen(),但是fopen_s()比较安全,区别见:http://blog.csdn.net/xiaojinzichen/article/details/47322061以及http://blog.163.com/lby147612@126/blog/static/1704104522011111452835960/

返回值的话,对于fopen来说,打开文件成功的话返回文件指针(赋值给fp),打开失败则返回NULL值;对于fopen_s来说,打开文件成功返回0,失败返回非0。

(2)简单的打开名为"lizi.txt"的文件并输出结果,采用fopen_s(),程序如下:

①读取一行

#include <stdlib.h>
#include <stdio.h>
int main()
{
char ch[20];
FILE *file;
int error = fopen_s(&file, "lizi.txt", "r");
if (!error == 0)
printf("打开文件失败.\n");
fgets(ch, 20, file);

// fgets()他可以读取一连串的字符串,但是会在碰到回车后停止读取,所以他读取我们的第一行。此处限制20个字符
fputs(ch, stdout);
system("PAUSE");
return 0;
}

②为了克服换fgets()只能读取第一行的缺点,此处采用循环改进:

#include <stdlib.h>
#include <stdio.h>
int main()
{
char ch[20];
FILE *file;
int error = fopen_s(&file, "lizi.txt", "r");//"r"表示只读
if (!error == 0)
printf("打开文件失败.\n");
while (fgets(ch, 20, file) != NULL)//增加循环来读取所有行
fputs(ch, stdout);
system("PAUSE");
return 0;
}

(3)读取并写入另一个文档,将"r"改成"w",并且新建一个file2

#include <stdlib.h>
#include <stdio.h>
int main()
{
char ch[20];
FILE *file;
FILE* file2;
int error = fopen_s(&file, "lizi.txt", "r");
fopen_s(&file2,"write.txt", "w");//"w"表示写入一个新文档
if (error!=0)
printf("打开文件失败.\n");
while (fgets(ch, 20, file) != NULL)
fputs(ch, file2);//将ch读取到的字符串写入file2名为"write.txt"的文档中
system("PAUSE");
return 0;
}

(4)输入文件名和写入文件名,随意打开文件,其实就是通过gets_s()和puts()两个函数获取了文件名而已

#include <stdlib.h>
#include <stdio.h>
int main()
{
char ch[20], name1[20], name2[20];
FILE *file;
FILE* file2;
puts("请输入需要打开的文件名:");
gets_s(name1);
puts("请输入需要写入的文件名:");
gets_s(name2);
int error = fopen_s(&file, name1, "r");
fopen_s(&file2, name2, "w");//"w"表示写入一个新文档
if (error != 0)
printf("打开文件失败.\n");
while (fgets(ch, 20, file) != NULL)
fputs(ch, file2);//将ch读取到的字符串写入file2名为"write.txt"的文档中
system("PAUSE");
return 0;
}

注意:在输入文件名时记得带上路径,比如说如果我们想要打开一个D盘下面的文件,我们可以这么写:D:\\lizi.txt

2.文件的操作

fopen()的原型:

FILE *fopen(

   const char *filename,
  const char *mode );

第一个参数就是我们要打开或者是创建的文件名,第二个参数是打开模式,打开模式我们可以有下面几种类型。

"r"   打开一个文本文件, 只读模式。

"w"   打开一个文本文件,只写模式,并且先将文件的长度截为零。如果该文件不存在则先创建文件。

"a"   打开一个文本文件,可以写入文件,向已有文件的发问追加内容,如果该文件不存在则先创建文件。

"r+"   打开一个文本文件, 可以进行更新,即可以读取和写入文件。

"w+"   打开一个文本文件, 可以进行更新 (读取和写入), 如果该文件存在则首先将其长度截为零, 如果不在则先创建文件。

"a+"   打开一个文本文件,可以进行更新 (读取和写入), 向已有文件的尾部追加内容,如果该文件不存在则先创建之;可以读取整个文件, 但写入时只能追加内容。

以二进制的方式操作文件,b既是表示二进制,意义和上面一样:"rb" "wb" "ab" "ab+" "a+b" "wb+" "w+b" "ab+" "a+b"

3.文件的定位fseek()和ftell()

(1)fseek()原型:

int fseek( 
     FILE *stream,//第一个参数是FILE的指针,也就是我们打开文件fopen的返回指针。
     long offset,//第二参数是偏移量,我们要想访问文件像访问数组一样简单就是靠这个参数。
     int origin //第三个参数就是读取模式
);

  第三个参数有三种类型:

SEEK_SET              文件开始

SEEK_CUR              当前位置

SEEK_END              文件结尾

第二个参数要起作用就是靠这第三个参数,第三个参数就是第二个参数偏移的原地,可以为负,可以为正,当为负的时候表示向后移,若为正表示向前移。

(2)ftell()原型:

long ftell( 
        FILE *stream 
);

这个函数返回从文件开头到定位处的字符个数,是一个long类型。所以在我们得到这个long值后  ,我们就可以用一个for循环控制输出。

(3)读取程序

#include <stdlib.h>
#include <stdio.h>
int main()
{
char ch, name1[20];
FILE *file;
long count, last;
puts("请输入需要打开的文件名:");
gets_s(name1);
int error = fopen_s(&file, name1, "r");
if (error != 0)
puts("打开文件失败.");
fseek(file, 0L, SEEK_END);//从文件结尾读取,定位到末尾
last = ftell(file);//读取从文件开头到定位处(末尾)的字符数,与fseek配合使用
for (count = 0L; count<last; count++)
{
fseek(file, -count, SEEK_END);//定位
ch = getc(file);//读取字符
if (ch != NULL);
putchar(ch);//输出字符
}
system("PAUSE");
return 0;
}

(4)扩展:

 fseek和ftell这对函数有个极限性,那就是限定文件在long范围内,为了解决的这个问题,还有另外一对函数(字符超过2亿):

int fgetpos (FILE * restrict stream, fpos_t * restrict pos);

int fsetpos (FILE * stream, const fpos_t *pos);









1 0
原创粉丝点击