博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于C语言判断文件尾问题的探讨
阅读量:6761 次
发布时间:2019-06-26

本文共 2343 字,大约阅读时间需要 7 分钟。

前些天心血来潮,准备做一个异或加密工具,用Java写了一个,感觉不过瘾.Java这东西还要依靠虚拟机运行.所以,准备再用C语言实现一遍.
还是参考HP UX的CP命令代码,如下:

 

 

HP UX CP
 1 
#include 
<
stdio.h
>
   
 2 
#include 
<
stdlib.h
>
   
 3 
 4 
int
 main(
int
 argc,
char
 
*
argv[])
 5 
{   
 6 
    
int
 ch;   
 7 
    FILE 
*
fpinPtr,
*
fpoutPtr;   
 8 
    
 9 
    
if
 (argc
!=
3
)
10 
    {   
11 
        printf(
"
File copy program.\n\n
"
);   
12 
        printf(
"
Usage: command source_file target_file\n
"
);   
13 
        printf(
"
Usage example: \
"
copy src.txt obj.txt\
"
\n
"
);   
14 
        exit(EXIT_FAILURE);   
15 
    }   
16 
    
17 
    
if
 ((fpinPtr
=
fopen(argv[
1
],
"
rb
"
))
==
NULL)
18 
    {   
19 
        printf(
"
Input file \
"
%
s\
"
 could not be opened\n
"
,argv[
1
]);   
20 
        exit(EXIT_FAILURE);   
21 
    }   
22 
    
23 
    
if
 ((fpoutPtr
=
fopen(argv[
2
],
"
wb
"
))
==
NULL)
24 
    {   
25 
        printf(
"
Outout file \
"
%
s\
"
 could not be opened\n
"
,argv[
2
]);   
26 
        exit(EXIT_FAILURE);   
27 
    }   
28 
    
29 
    
while
(
!
feof(fpinPtr))
30 
    {   
31 
        ch
=
fgetc(fpinPtr);   
32 
        
if
(ch
>-
1
)   
33 
            fputc(ch,fpoutPtr);   
34 
    }   
35 
    
36 
    fclose(fpinPtr);   
37 
    fclose(fpoutPtr);   
38 
    
39 
    
return
 
0
;   
40 
41 

结果这次仔细看了一下,发现了一些小问题.

 

 这条CP命令是读取源文件单个字符然后写入目标文件的方法实现的.但是代码的第6行的变量类型是int,我想这不是浪费内存空间么,而且第32行有一句if(ch>-1) ,半天没搞懂当时写这段代码的程序员是怎么想的.于是,我把第6行改成 char ch; ,删除了第32行的代码.

 

编译链接一切正常,运行,校验源文件和目标文件的MD5值,不一样.晕了.

仔细对比源文件和目标文件,发现目标文件尾多了一个EOF字符,原来是这个道理.于是把原32行的代码改成if(ch > EOF),复制了一个文本文件,一切正常.然后又试着复制一个BMP文件,问题又来了.

复制位图文件后发现,目标文件比源文件要小很多,用记事本打开源文件,发现源文件里面就有许多EOF字符,这些字符都复制丢了.

而不加原始代码里32行的那句约束语句,则程序会多读取一个字符,如果是读取一个文件段,则会造成读取垃圾数据.

而原始代码正是解决了判断文件尾的问题.

 

网上有的帖子也说:

 

可以用feof()函数判断文件尾

也可以用fgetc读取内容

ch=fgetc(fp);

ch==EOF也是文件结尾 

 

看来也不完全对,如果用fgetc来判断,则有可能在读取位图这类二进制文件时会造成错误的文件尾提示,用feof则会多读取一次.

 

在此之前,我的师兄王晔用判断文件大小的方法复制文件,对小文件的操作或许可以采用.

附师兄的源码:

 

Wang Ye copy
 1 
#include 
<
stdio.h
>
 2 
#include 
<
stdlib.h
>
 3 
#define
 FILE_NAME "a.jpg"
 4 
int
 main(
void
)
 5 
{
 6 
    
char
 tmp;
 7 
    
long
 len;
 8 
    unsigned 
char
 
*
read_ptr;
 9 
    FILE 
*
=
 fopen(FILE_NAME, 
"
rb
"
);
10 
    FILE 
*
=
 fopen(
"
a1.jpg
"
"
wb
"
);
11 
12 
    
if
(NULL 
==
 p)
13 
        
return
 
1
;
14 
15 
    fseek(p, 
0L
, SEEK_END);
16 
    len 
=
 ftell(p);        
/*
求文件长度
*/
17 
    fseek(p, 
0L
, SEEK_SET);
18 
19 
    read_ptr 
=
 (unsigned 
char
 
*
)calloc(len, 
sizeof
(unsigned 
char
));
20 
21 
    
if
(NULL 
==
 read_ptr)
22 
    {
23 
        puts(
"
Error\n
"
);
24 
        
return
 
1
;
25 
    }
26 
    fread(read_ptr, len, 
1
, p);
27 
28 
    printf(
"
%x %x
"
*
read_ptr, 
*
(read_ptr 
+
 
1
));
29 
30 
    fwrite(read_ptr, len, 
1
, f);
31 
32 
    free(read_ptr);
33 
    fclose(p);
34 
    fclose(f);
35 
    
return
 
0
;
36 
}

 

参考文章:

转载于:https://www.cnblogs.com/Leon5/archive/2009/11/30/1614044.html

你可能感兴趣的文章
webservices 服务器未能识别 HTTP 头 SOAPAction 的值:.
查看>>
iOS应用开发,全局强制竖屏,部分页面允许旋转的处理
查看>>
Linux运维教程
查看>>
Git学习
查看>>
问到的问题
查看>>
iOS网络模块优化(失败重发、缓存请求有网发送)
查看>>
经典SQL语句大全(绝对的经典)
查看>>
中小研发团队架构实践之总体架构设计
查看>>
PDO中获取结果集
查看>>
实用主义性能测试
查看>>
oozie开发注意事项
查看>>
【Tomcat】linux下实时查看tomcat运行日志
查看>>
HDU 5212 Code
查看>>
yarn使用
查看>>
Hadoop之 MapReducer工作过程
查看>>
CPU监控
查看>>
MongoDB中的explain和hint提的使用
查看>>
redis集群部署及踩过的坑
查看>>
为什么许多人宁愿死,也不愿思考
查看>>
从内核源代码配置文件预測泛泰新品(A920 ?)
查看>>