文件结束的判断和结束符的理解

转载自:http://blog.csdn.net/zhy10/article/details/1562649

转载自:http://blog.csdn.net/sambian/article/details/644360

EOF,即end of file,文件结尾,作为文件结束的标志,在程序中常作为判断的一个标志。但在我们平常的程序中却常发生意想不到的结果。
下面这段程序,猜猜它输出的是什么?
char c;
ifstream fin("d://dat");//设d:/dat文件已存在,内容为ab。
while(!fin.eof())
{
    fin >> c;
    cout << c;
}
输出结果是abb,没想到吗?你可能会问,再输出第一个b的时候,文件指针已经指向了EOF,为何不结束?
问题的关键是文件EOF机制是怎样运作的。

我们来谈三个问题:

1、文件指针
当打开一个文件时,文件指针位置为0,并不是指向第一个字符,即第一个字符的位置为1。这一点我们可以通过peek()函数验证。peek()返回的是当前文件指针下一个位置的字符。所以有:
ofstream fo("d://dat");
fo << ‘h‘;
fo.close();
ifstream fi("d://dat");
char temp = fi.peek();
cout << temp;
会显示h。
还有,用fo.seekp(0,ios::beg),得文件指针为0;fo.seekp(0,ios::end),得文件指针指向最后一个字符。

2、关于EOF
很多朋友认为文件尾有EOF,这是错误的。EOF是流的状态标志。在 C++中,是在读取文件失败时才产生EOF。所以第一个程序中,在输出第一个b时,产生了EOF,再输出第二个b时读取到EOF,循环结束。

3、解决EOF困惑的办法
我感觉在判断文件结束上,最好的方法就是判断文件指针相对于开头的位置,是否等于文件长度。即:
long filelen;
ifstream fin("d://dat");//设d:/dat文件已存在,内容为ab。
fin.seekg(0,ios::end);
filelen = fin.tellg();//获取文件长度
fin.seekg(0,ios::beg);
while (1)
{
    if (filelen == fin.tellg())//到达文件尾,即指向EOF
    {
        flag = true;
        break;
    }
    读取数据...
}

当然还有别的方法,就是用peek()的预读性。
peek()返回当前文件指针下一个位置的字符,而指针位置不变。所以我们可以这样:
while (fi.peel()!=EOF)
{
    ...
}
当while循环体中,文件指针指向最后一个字符,若没有fi.peel()!=EOF,则需要再下一个循环中才能触发EOF。而加了fi.peel()!=EOF后,用预读的方法检测出了EOF。

#include <stdio.h>

int main()
{
    FILE *in,*out;
    char ch,infile[10],outfile[10];

printf("Enter the infile name:");
    scanf("%s",infile);
    in=fopen(infile,"r");
    
    if(in==NULL)
    { 
        printf("Can‘t open the file that you want read!");
        return 1;
    }

printf("Enter the outfile name:");
    scanf("%s",outfile);
    out=fopen(outfile,"w");
    if(out==NULL)
    { 
        printf("Can‘t open the file that you want to write!");
        return 1;
    }

while(!feof(in))
    { 
        ch=fgetc(in);
        putchar(ch);
        fputc(ch,out);
    }
 
    fclose(in);
    fclose(out);
    
    return 0;
}

上面这个小程序,每次运行后,目标文件会比源文件多一个字节,比如,源文件Test1.txt的内容是:
hehe
运行后,目标文件Test2.txt的内容却是:
hehe
用记事本打开看的,多了一个字节,变成了5字节

上面这段程序在谭浩强的C程序设计(第二版)中也有这个问题,这实际上是对feof这个函数的处理方式不理解所造成的,实际上:

当feof(FILE *)读到EOF标志并不认为文件结束了,依旧返回0,直到读到EOF的下一个字符才返回1,这时才认为是文件结束。

因此若以while(!feof(fp))为循环条件的时候,要将一个文件(fp)完全复制到另一个文件(fp1),需要加上判断if(ch!=-1),如下:

while(!feof(in))
 {
  ch=fgetc(in);
  if(ch!=-1)
  fputc(ch,out);

}

或者:

while(true)
    { 
        ch=fgetc(in);
        if(feof(in))
         break;
        putchar(ch);
        fputc(ch,out);
    }

时间: 2024-10-20 01:31:29

文件结束的判断和结束符的理解的相关文章

判断文件结束函数 feof

在上一节例2中,程序从一个文件中逐个读取字符并输出到屏幕上显示,在 while 循环中以 EOF 作为文件结束的标志.这种以 EOF 作为文件结束标志的文件,必须是文本文件.在文本文件中,数据都是以字符的 ASCII 码值的形式存放.我们知道,ASCII 码值的范围是 0~255,不可能出现 -1,因此可以用 EOF 作为文件结束的标志. 当把数据以二进制形式存放到文件中时,就会有 -1 值的出现,此时不能采用 EOF 作为二进制文件的结束标志.为解决这一问题,ANSI C 提供一个 feof

判断文件结束,feof……

因为文本文件中存储的是ASCII码,而ASCII码中FF代表空值(blank),一般不使用,所以如果读文件返回了FF,说明已经到了文本文件的结尾.但是如果是二进制文件,其中可能会包含FF,因此不能把读到EOF作为文件结束的条件,此时只能用feof()函数. 在VC里,只有当文件位置指针(fp->_ptr)到了文件末尾,然后再发生读/写操作时,标志位(fp->_flag)才会被置为含有_IOEOF.然后再调用feof(),才会得到文件结束的信息.因此,如果运行如下程序: char c; whil

feof()和EOF的用法—— C中文件结尾的判断

查看 stdio.h 可以看到如下定义: #define EOF (-1) #define _IOEOF 0x0010 #define feof(_stream) ((_stream)->_flag & _IOEOF) 由此可以看出,这两种方式的原理是不同的. 在这里先说下EOF和feof()这个两个宏定义,在我们学的课本中有这样的描述. EOF是不可输出字符,因此不能在屏幕上显示.由于字符的ASCII码不可能出现-1,因此EOF定义为-1是合适的.当读入的字符值等于EOF时,表示读入的已不

fstream读取文件时如何判断读到文件尾

使用fstream读取文件,什么时候读到文件结束呢.首先想到的是,将现在的位置与文件的长度对比,然后再fstream中无法直接获取文件长度.可以采用如下方法 fstream in; in.open("path",ios::in); in.seekg(0,ios::end); int length=in.tellg(); in.seekg(0.ios::beg); whiel(in.tellg()<length) { dosomething; } 这样是不是有点麻烦,在网上查了一圈

输入一串字符,字符个数不超过100,且以“.”结束。 判断它们是否构成回文。

输入一串字符,字符个数不超过100,且以“.”结束. 判断它们是否构成回文. [分析]所谓回文指从左到右和从右到左读一串字符的值是一样的,如12321,ABCBA,AA等.先读入要判断的一串字符(放入数组letter中),并记住这串字符的长度,然后首尾字符比较,并不断向中间靠拢,就可以判断出是否为回文. 程序如下: #include<iostream>using namespace std;int main(){ char ch,letter[101]; cin>>ch; int

C语言关于“输入包含多行数据,请处理到文件结束”的问题

今天,笔者在做本校ACM校赛网络赛的时候,遇到输入格式中有这样的要求:输入包含多行数据,请处理到文件结束.题目的逻辑很简单,主要功能代码很容易实现,但是题目中没有“明确”指出控制台中输入数据以什么方式结束,例如:#.双回车等等.笔者尝试了利用clock_t变量控制程序运行时间,但是在评判平台显示“编译错误”.在认真分析后,笔者得到答案,“输入包含多行数据,请处理到文件结束”的含义是,当输入足够数据后,可以使用“Ctrl+Z”退出控制台,即为“处理文件结束”,原因是:Ctrl+Z会使scanf()

java打开文件夹(含判断操作系统工具类和解压缩工具类)

1.Runtime.getRuntime().exec("explorer D:\\Java"); 2.java.awt.Desktop.getDesktop().open(new File("D:\\Java")); 4.java.awt.Desktop.getDesktop().browse(...) 3. try { String[] cmd = new String[5]; cmd[0] = "cmd"; cmd[1] = "/

使用feof()判断文件结束时会多输出内容的原因

这是原来的代码: #include <stdio.h>int main(){    FILE * fp;    int ch;    fp = fopen("d:\\aaaaa\\1.txt","r");    while (!feof(fp))    {        ch = getc(fp);        putchar(ch);    }    fclose(fp);    return 0;} 以此来输出时会发现好像输出的内容在结尾部分多了一

C#文件相同性判断

在进行开发时,对文件进行上传和下载是较为普遍的行为,为了防止在文件操作过程中,出现同一文件多次操作,需要对文件进行相同性比较: 1.获取文件的绝对路径,针对window程序和web程序都可使用: /// <summary> /// 获取文件的绝对路径,针对window程序和web程序都可使用 /// </summary> /// <param name="relativePath">相对路径地址</param> /// <retur