-
C# 读取二进制文件 判断文件结束的方法
2012-01-05 09:04:58网上资料中很多是通过try catch 获取文件是否读取完毕. 总觉着这种捕获异常的方式太丑陋.于是找到了另外一种更好的方式. 可直接判断文件结束. FileStream fs = File.OpenRead(path); BinaryReader brReader = ...网上资料中很多是通过try catch 获取文件是否读取完毕. 总觉着这种捕获异常的方式太丑陋.于是找到了另外一种更好的方式. 可直接判断文件结束.
FileStream fs = File.OpenRead(path); BinaryReader brReader = new BinaryReader(fs); while (brReader.BaseStream.Position < brReader.BaseStream.Length) { //TODO } brReader.Close();
或者:
using (BinaryReader br = new BinaryReader(fs)) { while (br.PeekChar() > -1) { //TODO } }
-
为什么“-1”能作为判断文本文件结束的标志然而为什么不能作为二进制文件是否结束的标志?
2017-03-03 10:51:03这种使用“-1”作为判断文本文件的结束标志而不能作为判断二进制文件是否结束。尽管二进制文件的结尾标记也是-1,当程序读取到一个正好为-1的字节时,就难以偶按段是文件结尾还是文件中的有效数据。 对于标准的...在java中,由于没有编码为-1的字符,所以操作系统就使用-1作为硬盘上的每个文件的结束标志。
这种使用“-1”作为判断文本文件的结束标志而不能作为判断二进制文件是否结束。尽管二进制文件的结尾标记也是-1,当程序读取到一个正好为-1的字节时,就难以偶按段是文件结尾还是文件中的有效数据。
对于标准的二进制文件,在文件开始的部分,都有一个文件头指定文件的大小,程序就是凭借文件头中的这个大小来读取文件的所有内容。
-
C语言文件读写(4)-判断文件是否结束
2020-07-01 08:37:33判断文件结束,有许多方式,比如读取文本文件和二进制文件就可以使用不同的方式,下面分别进行详细介绍和举例。 使用EOF判断文件是否结束 EOF的值为-1,所以往往使用EOF也可以判断文件是否结束,一般用在非格式化...C语言文件读写-判断文件是否结束
在读文件的时候,很重要的一个条件是:文件是否结束,因为文件已经结束了,就不用继续读文件了。
判断文件结束,有许多方式,比如读取文本文件和二进制文件就可以使用不同的方式,下面分别进行详细介绍和举例。
使用EOF判断文件是否结束
EOF的值为-1,所以往往使用EOF也可以判断文件是否结束,一般用在非格式化文本文件读取中,如果在格式化文本读取时使用EOF来判断,在某些情况下是会出错的。
函数fgetc返回的值为一个字符,当文件结束时,返回EOF,因为文本文件中可打印字符没有字符的值是-1,所以,可以用EOF来判断文件是否结束了。
这也是唯一的一个可以使用EOF来判断文件是否结束,而且永远正确的函数,前提是必须是读文本文件(格式化或者非格式化都可以支持)。
我们来看一下使用fgetc和EOF来检测文件是否结束的例子,代码如下:
void EOF_test_getc(const char* file_name) { int ch = 0; int count = 0; FILE *file = fopen(file_name,"r"); if(!file) return; while(1) { ch = fgetc(file); if(ch == EOF) { printf("reach the end of file,the char number is %d\n",count); break; } else { count++; putchar(ch); } } fclose(file); }
在代码中,我们使用fgetc来读取文件中的每一个字符,如果读取到的字符是EOF,则结束读取,每读取一个字符,就对count++,以统计文件中字符的个数。运行效果如图所示。
但是出现了一个奇怪的问题,程序中统计出来的字符是98个,但是文件大小却是102个字节,相差了4个字符,那4个字符到哪里去了?
中提到,在Windows上,如果写入行结束符'\n',系统会自动替换为'\r\n',在读取的时候,会自动把'\r\n'转换为'\n',因为我们这个文件有4行,所以文件中就多了4个'\r',这就是为什么文件的实际大小会比读取出来的字符多了4个的原因。
注意,这种判断文件结束的方式只能针对文本文件,不能用在二进制文件上面,因为二进制文件的内容什么值都可以存储,-1也会是其中的一个值。
fscanf和fscanf_s有时候也可以用EOF来判断文件是否结束,而且在前面的几篇文章中也确实使用了这种方式来判断,但是,如果文本文件中的内容一旦有一点错,scanf中的format字符串不能匹配,则永远都不会返回EOF这个值,就会造成死循环,所以在使用fscanf或者fscanf_s的时候,不推荐使用返回值EOF来判断文件是否结尾,而是使用feof函数来检测,后面会介绍。
使用是否为NULL来判断
函数fgets用来获取一行的文本文件数据,如果返回为NULL,则表示文件结束了或者读取错误,所以有时候也可以使用返回值是否为NULL来判断文件是否结束,示例代码如下:
void read_text_by_gets(const char* file_name) { char buffer[128]={0}; FILE *file = fopen(file_name,"rt"); if(!file) return; while(NULL != (fgets(buffer,sizeof(buffer),file))) { //显示每一次读取到的内容 printf("%s",buffer); } fclose(file); }
这在绝大多数的时候都可以判断文件是否真的结束了,但是,如果读取文件出错了,也会返回NULL,这就不能区分是文件真的结束了,还是由于别的原因读取错误,所以,并不推荐用这种方式来检测文件是否结束。
通过返回值的大小来判断
我们在使用fread来读取二进制文件的时候,往往可以通过返回值是否等于count的值来判断文件是否结束,大多数情况下是没有问题的,示例代码如下:
void read_binary_file(const char* file_name) { struct Student stu={0}; FILE *file = fopen(file_name,"rb"); if(!file) return; while(fread(&stu,sizeof(stu),1,file) == 1) { printf("学号:%d 姓名:%s 学院:%s 分数:%.2f\n",stu.ID,stu.Name,stu.College,stu.Score); } fclose(file); }
在示例代码中,fread因为我们每次只读一个Student的大小,所以如果返回的值小于1的话,则说明文件结束了。
同样的原因,fread如果出错了的话,返回值也是可能小于1的,因此这个判断也不是100%准确的。
使用feof来判断
feof的原型为:
int feof( FILE *stream );
返回值是一个整数,如果为0,表示文件没有结束,如果非0,表示文件结束。
但是要特别注意一点的是,这个函数的实现机制是这样的:
是在下一次读取的时候判断是否到了文件末尾,如果是,则设置文件结束标志,它并不是在调用feof这个函数的时候去检查数据来判断是否到了文件的末尾。所以这个函数的使用,很多朋友都会用错,以为这是一个真正检查文件是否结束的函数,当然,它确实是,但是它不是即时的。
我们先看一下文本文件的例子,仍然以刚才的student.txt为例,代码如下:
void feof_test_getc(const char* file_name) { int ch = 0; int count = 0; FILE *file = fopen(file_name,"r"); if(!file) return; while(!feof(file)) { count++; ch = fgetc(file); putchar(ch); } printf("reach the end of file,the count is %d\n",count); fclose(file); } int main(int argc, char* argv[]) { feof_test_getc("student.txt"); return 0; }
这个代码几乎是我遇到的所有初学C语言甚至是学了C语言很长时间的朋友的写法,确实,看起来没有任何问题,我们来看一下运行结果,如图所示。
请注意,count的值是99,而且最后一行还多输出一个字符,这就是为什么在论坛上会经常看到为什么会多出一行,多出一个之类的讨论。
这确实就是缺乏对feof的理解造成的,我们以为feof就是一个实时监测文件是否结尾的函数,其实并不是,当你使用fgetc或者任何别的函数读取文件内容的时候,如果读取的内容刚好是文件的最后一个字符,这个时候调用feof的话,返回仍然是0,因为它并不会去真的检查文件是否结尾,它要依赖下一次的读取操作,下一次再次读取的时候,发现文件已经到了结尾,则设置文件结束标志,feof调用的时候才会返回非0值。
现在来演示一下一个代码,可以更好地理解feof的工作机制,代码如下:
void feof_test() { int test = 0; char ch = 't'; char str[20]="test"; FILE *file1,*file2,*file3; //第一种情况 file1=fopen("test1.dat","w+"); fprintf(file1,"%c",ch); rewind(file1); fscanf(file1,"%c",&ch); if(feof(file1)) { printf("文件1结束\n"); } else { printf("文件1没有结束\n"); } fclose(file1); //第二种情况 file2=fopen("test2.dat","w+"); fprintf(file2,"%d",10); rewind(file2); fscanf(file2,"%d",&test); if(feof(file2)) { printf("文件2结束\n"); } else { printf("文件2没有结束\n"); } fclose(file2); //第三种情况 file3=fopen("test3.dat","w+"); fprintf(file3,"%s",str); rewind(file3); fscanf(file3,"%s",str); if(feof(file3)) { printf("文件3结束\n"); } else { printf("文件3没有结束\n"); } fclose(file3); }
在这个测试中,写入三个文件,然后分别打开对应的文件从头开始读取,然后判断feof是否返回非0值,其中第一种情况,返回0,第二种和第三种返回非0。
先看一下运行结果,再来解释为什么。结果如图所示。
为什么会产生这个差别呢?先说第一种情况,写入了一个字符,然后读取一个字符,虽然文件中只有一个字符,但是读取一个字符就够了,所以并不知道文件是否结束。
第二种情况,写入数字10到文件,然后读取一个整数,为什么就检查到文件结束了呢?因为读取一个整数的时候,会一直读,直到读取到空格或者别的结束符或者超过整数范围的时候才会结束,因为文件中存的是10,所以会一直读到文件结束,10是没有超过整数范围的。
第三种情况和第二种情况一样,读取一个字符串的时候也要一直读,直到遇到空格或者tab之类的,由于文件中只有test这四个字符,自然就会读到文件尾了。
所以第二和第三种情况都会返回非0值,表示文件结束了。
-
c++判断文件读取结束_C++快速入门学习笔记2|关于文件复制
2021-01-18 17:24:34编写一个文件复制程序C语言:思路:1、 首先确保输入参数个数正确,否则抛出错误2、 然后用if ((in = fopen(argv[1], "rb")) == NULL)这个语句实现了用二进制可读打开源文件,并且将地址传给指针in,然后还判断了...《C++快速入门》学习笔记
b站指路:鱼C-小甲鱼
进度:P4
编程任务:编写一个文件复制程序
C语言:
思路:
1、 首先确保输入参数个数正确,否则抛出错误
2、 然后用if ((in = fopen(argv[1], "rb")) == NULL)这个语句实现了用二进制可读打开源文件,并且将地址传给指针in,然后还判断了是否打开成功这三个功能。如果成功就返回指针,否则抛出错误。
3、 再用if ((out = fopen(argv[2], "wb")) == NULL)这个语句实现了和上面差不多的功能(注意是可写形式打开),值得注意的是这一块if语句当中加入了fclose(in),是为了防止【源文件能打开但是目标文件无法打开】的情况,在读取下一句退出之前关闭了输入流文件,确保了文件的安全性。这个地方容易出隐藏的bug。
4、 在确保以上无误的情况下,用while ((ch = getc(in)) != EOF)语句来不断读取in当中的字符,如果遇到文件尾,那么跳出循环。里面嵌套的if (putc(ch, out) == EOF)语句也同样实现了把ch写入输出流,同时判断是否遇到文件尾的两个功能。这一块是实现文件复制的核心。
5、 最后用ferror()来判断是否是文件读取/写入错误导致返回EOF提前结束程序(因为返回EOF的情况有文件尾和读写错误两种)
6、 最后fclose()关闭文件
【关于传入参数】
argc是整型变量,是程序的参数数量,包含本身
argv[]是字符指针数组,每个指针指向命令行的一个字符串
argv[0]指向字符串“copyFile.exe”
argv[1]指向字符串sourceFile
arge[2]指向字符串destFile
【关于文件指针】
in和out是我们声明的两个文件指针,分别作为两个I/O流对象使用(文件是存储在磁盘上的,我们要使用的时候就需要将其拿到内存中,故要进行内存的分配,故使用FILE*的指针来操作)
【关于getc()】
Each of these functions returns the character read. To indicate an read error or end-of-file condition, getc and getchar return EOF.
注意:
getc()返回值是int类型,所以我们声明时是int ch,而不是char ch
C++:
思路和上面C语言相同:
1、ifstream in("test.txt")在声明的过程当中就调用了构造函数,如果打开失败,那么会返回一个0,故下面一句if (!in)用来判断打开失败的情况。
2、接着用一个字符x来从in当中接收字符,再流出,最后关闭文件
Ifstream其实是一个文件输入流的类,我们声明了它的对象in,那么in就拥有了这个类的属性。
C++相比C语言的优势就在于声明类的对象的时候,这个对象就有了类的属性,代码更加简洁清晰,封装性很强。
在构造的时候可以加入第二个参数表示打开模式,
常见的几种打开模式:
Ios::in—打开一个可读取文件
Ios::out—打开一个可写入文件
Ios::binary—以二进制形式打开
Ios::app—写入的数据追加到文件末尾
Ios::trunk—删除文件原来已存在的内容
Ios::nocreate—如果要打开的文件不存在,那么无法执行
Ios::noreplece—如果要打开的文件已存在,则返回错误
同时应用多种打开模式:
可以用|来连接,因为它们的本质是枚举类型,转化成二进制后对应着1,10,100,1000等等,占据了不同的位,那么进行|的运算时,1|100的运算结果就是101,这样就可以通过读取每一位来判断分别是哪几种打开模式
写在后面:
关于文件的修改等内容以后还需要更多注意,尤其是main函数当中传入参数这一点,因为归根到底这一部分我还没有办法跑起来x
C语言的版本在VS2019当中会无法运行,原因就是fopen()被认定为不够安全,而C++版本的代码是我自己参考小甲鱼给的几个示例摸索着写的,所以没能实现“输入文件名进行操作”这一点,代码不够灵活。在仿照上面C语言的传参方式的时候,能通过编译,但是程序没给我输入的机会em
C++在对于重复代码的使用这一块上面让人感觉到比C语言的效率更高一些。
最后还有一点就是,在读取不确定长度的内容时,一个思路就是用循环读取,在尾部跳出。
IT双侠的咕咕咕日常
内容:咸哥
排版:咸哥
特别鸣谢:小甲鱼
-
关于文件读取中读到文件末尾的判断方法feof()会多读一次数据的机制和解决方案
2020-06-27 16:28:32说明: EOF是文本文件结束的标志。在文本文件中,数据是以字符的ASCⅡ代码值的形式存放,普通字符的ASCⅡ代码的...feof函数既可用以判断二进制文件又可用以判断文本文件。feof(fp)如果文件结束则返回非0值,否则返回0。 -
关于文件结束的判定
2019-06-23 19:26:03在文件的读取过程中,feof函数的返回值不能直接用来判断文件是否结束.正确的用法是当文件读取结束时,判断是读取失败结束,还是遇到了文件尾结束. 判断文本文件的读取是否结束,需要判断其返回值是否...对于二进制文件的... -
feof()函数读取文件和EOF结束符标志问题
2010-05-01 10:50:00windows下的txt文本文件中的内容都是ASC Ⅱ代码值的...但是对于二进制文件来说,-1确实是可以出现的。 feof()函数在c/c++中是用来判断当前要操作的文件是否结尾,如果文件已结尾,返回值为1,否则就返回0.它判断文件 -
(四)关于读文件的结束的判别方法(EOF和feof)以及区别
2018-04-12 19:53:00关于读文件的时候判断文本是否读完的方式一般可以... 当以二进制形式读取文件内容, 信息都是以数值方式存在的, EOF的值可能就是所要处理的二进制文件中的信息, 此时需要用 feof() 来判断是否到达了文件结尾 即EO... -
java IO操作
2019-12-22 14:49:21Java Reader/Writer read源码 ...这种使用“-1”作为判断文本文件的结束标志而不能作为判断二进制文件是否结束。尽管二进制文件的结尾标记也是-1,当程序读取到一个正好为-1的字节时,就难以偶按段... -
关于EOF和feof()判断文件读到末尾
2015-03-25 19:55:51判断文件读取是否到了结尾有两种方式,一种是判断fgetc()是否返回EOF(即-1,一个宏定义);另一中是使用feof()函数判断,如果结束返回1,否则返回0; 第一种方式局限性很大,因为只有fgetc(),fscanf()遇到结束返回EOF,... -
13.第十三章 文件.txt
2019-11-08 16:33:27二进制文件是直接用数据的二进制形式存放的,即把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。 程序中实现对文件的处理通常分三步: (1)打开文件:将程序与文件建立联系。 (2)操作文件:对... -
如何编写批处理文件批处理文件批处理文件
2010-04-14 10:36:10然后if语句将作出判断,d表示执行标号为defrag的程序段,m表示执行标号为mem的程序段,e表示执行标号为end的程序段,每个程序段最后都以goto end将程序跳到end标号处,然后程序将显示good bye,文件结束。... -
e语言-网页_访问_对象 实现网络文件断点传输还带进度条
2019-08-23 11:53:57网络文件传输断点续传,带进度条和判断文件是否一致还有就是重复文件自动重命名。有点多线程基础的可以自己弄成多文件 多线程下载哦,这一个HTTP头记录一下,可以的话或者能帮到别人。在HTTP/1.1协议没出的时候,也... -
第一周总结
2020-02-09 22:10:002、失败的时候,遇到文件结束符,返回EOF 判断浮点数是否等于某个值 0.0001 短路操作 右移 : 1、正数 除2 2、负数 减一除二 3、无符号数 高位和低位补0 也是除二 统计一个数对应二进制中【1】的个数或者【0】的个数... -
C语言程序设计标准教程
2009-05-22 20:04:03其意义是打开C驱动器磁盘的根目录下的文件hzk16, 这是一个二进制文件,只允许按二进制方式进行读操作。两个反斜线“\\ ”中的第一个表示转义字符,第二个表示根目录。使用文件的方式共有12种,下面给出了它们的符号... -
C开发金典随书源码:含数据结构 数值计算分析 图形图像处理 目录和文件操作 系统调用方面的范例
2013-10-25 13:12:12范例1-51 判断双向链表是否为空 126 ∷相关函数:ListEmpty函数 1.3.21 双向链表元素值的查询 129 范例1-52 双向链表元素值的查询 129 ∷相关函数:GetElemP函数 1.3.22 稀疏矩阵的建立 136 范例1-53 稀疏矩阵... -
加密和解密 第二版 段钢 PDF
2010-01-17 21:02:1916.2.1 判断文件是否为PE格式 16.2.2 文件基本数据读入 16.2.3 附加数据读取 16.2.4 输入表处理 16.2.5 重定位表处理 16.2.6 文件的压缩 16.2.7 资源数据处理 16.2.8 区块的融合 16.3 外壳部分编写 16.3.1 外壳的... -
易语言 茶凉专用模块
2010-05-04 12:26:36子程序 到任意进制, 文本型, 公开, 可以将从二进制到三十六进制的数值随意进行转换(返回转换后的文本) .参数 被转换文本, 文本型, , 欲被转换的文本(不可以转换负数以及小数) .参数 被转换进制, 整数型, , 被转换... -
入门学习Linux常用必会60个命令实例详解doc/txt
2011-06-09 00:08:45文件为doc版,可自行转成txt,在手机上看挺好的。 本资源来自网络,如有纰漏还请告知,如觉得还不错,请留言告知后来人,谢谢!!!!! 入门学习Linux常用必会60个命令实例详解 Linux必学的60个命令 Linux提供... -
大量批处理实用程序例程
2018-05-17 21:06:30十进制转二进制.cmd 十进制转十六进制.cmd 字母大小写转换.cmd 把秒转换为天小时分秒的格式.cmd 阿拉伯与罗马数字互转程序.cmd 阿拉伯数字转为罗马数字.cmd C盘个人资料转移器 IE修复.cmd Windows安全优化小助手.cmd... -
C#编程经验技巧宝典
2008-06-01 08:59:3398 <br>0153 如何自定义数字小数点左边分组位数 98 <br>0154 格式化输入数据为货币格式 99 <br>0155 如何计算两个整数的乘积 99 <br>0156 如何将二进制数转换为十进制数 100 <br>0157 如何... -
网管教程 从入门到精通软件篇.txt
2010-04-25 22:43:49BIN:二进制文件 BINHex:苹果的一种编码格式 BMP:Windows或OS/2位图文件 BOOK:Adobe FrameMaker Book文件 BOX:Lotus Notes的邮箱文件 BPL:Borlard Delph 4打包库 BSP:Quake图形文件 BUN:CakeWalk 声音... -
300多个bat-cmd-dos批处理程序代码.rar
2020-04-05 15:23:08十进制转二进制.cmd 十进制转十六进制.cmd 字母大小写转换.cmd 把秒转换为天小时分秒的格式.cmd 阿拉伯与罗马数字互转程序.cmd 阿拉伯数字转为罗马数字.cmd 2000XP停止打印.bat 2003优化文件.bat 98下获取... -
700个批处理打包下载.rar
2013-08-12 17:45:52十进制转二进制.cmd 十进制转十六进制.cmd 去掉字符串不同部位的空格.cmd 去掉字符串头所有的0.cmd 去掉数值中可能存在的负号.cmd 去最大最小值后求剩余数组平均值.cmd 反序列出文本的每行内容.cmd 反序显示输入内容... -
易语言模块大全
2018-08-07 13:01:30判断XP外观支持文件是否存在.ec 判断字符模块.ec 判断数据库.ec 判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功能集一模块.ec 加入好友.ec 加密.ec 加密解密文本.... -
Visual C++编程技巧精选500例.pdf
2012-09-01 15:01:50213 如何检测文件是否已经发生更改? 214 如何判断文件在磁盘上是否存在? 215 如何读写INI文件? 216 如何创建一个临时文件? 217 如何创建一个特大型文件? 218 如何创建一个文本文件? 219 如何删除一个文本文件? 220 ... -
精易模块[源码] V5.15
2015-03-21 22:03:374、新增“窗口_是否被遮挡”,判断一个窗口是否被置顶窗口遮挡,代码由易友【@shituo】提供。 5、改善“汇编类->置入汇编代码”增添一个参数是否保留以前代码。感谢易友【@无名侠】反馈。 6、修正“文本_加密”返回... -
delphi通用函数单元一
2011-08-19 20:38:47{* 判断文件是否正在使用} function GetFileSize(FileName: string): Integer; {测试通过} {* 取文件长度} function SetFileDate(FileName: string; CreationTime, LastWriteTime, LastAccessTime: TFileTime): ... -
AutoLISP学习导引.pdf
2015-07-18 22:45:17负整数二进制值推算法 79 4位有符号整数表 79 最大与最小整数之外 79 重点复习 80 进阶挑战 81 实数 82 实数范围 82 实数的有效位数 83 误差 85 累积误差 86 重点复习 87 进阶挑战 88 字符串与字符 89 改变字母的大... -
易语言模块914个
2018-03-12 20:00:21判断XP外观支持文件是否存在.ec 判断字符模块.ec 判断数据库.ec 判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功能集一模块.ec 加入好友.ec 加密.ec 加密解密文本....
-
深究字符编码的奥秘,与乱码说再见
-
无
-
C++代码规范和Doxygen根据注释自动生成手册
-
一张完整的中国亲戚关系图
-
Python 网易新闻热点新闻爬虫
-
RFC3261-中文版本.zip
-
衍射误差对相位校正效果的影响
-
【比赛笔记】异常检测-二
-
二极管抽运全固态1.319 μm连续锁模激光器
-
性能测试基础--(CPU)
-
PaddleOCR 生成C++环境 demo
-
wifi P2P 自己总结的文档
-
HTML&CSS3.md
-
PPTP_NNN 服务生产环境实战教程
-
中文纠错工具简单词频统计
-
2021年建筑电工(建筑特殊工种)考试报名及建筑电工(建筑特殊工种)操作证考试
-
使用 Linux 平台充当 Router 路由器
-
libFuzzer视频教程
-
2021年T电梯修理模拟试题及T电梯修理理论考试
-
yolov4_opencv411.7z