读取文件遇到0X1A意外终止的解决方法
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
在Windows的集成开发环境中(Qt、VC、VS中均存在该问题)编写有关文件读取的C/C++程序,出现读取到0X1A的时候意外终止的情况,经调试检查发现0X1A经过读取之后被处理成0XFF(即EOF(-1)),但是Linux中(Redhat6.4以及Ubuntu14.04中测试)不存在这种解析错误的问题。关于出现这种问题的原因可参考:https://blog.csdn.net/zhoubl668/article/details/7054282。那么解决办法有两种:
1、用二进制的方式读取:
FILE * fp = fopen("file", "rb");//以二进制流读取
以“.dcm”的文件解析为例(将new.dcm的信息解析成十六进制输出到new.hex中去):
/*
* 2018年4月20日16:37:10
* 二进制流的方式读取
*
*/
#include "stdafx.h"
#define STRING_BUFFER 16
char strbuf[STRING_BUFFER] = {0};
int main(void)
{
unsigned int i = 0;
FILE * fpr = fopen("F:\\new.dcm", "rb");//以二进制流读取
FILE * fpw = fopen("F:\\new.hex", "w");//输出文件
if(fpr == NULL || fpw == NULL){
printf("open file failure at line:%d\n", __LINE__);
exit(EXIT_FAILURE);
}
fprintf(fpw, "%08X: ", num);
while(!feof(fpr)){//直接用feof()可以判断
int ch = fgetc(fpr);//一次读取一个字符
strbuf[num % STRING_BUFFER] = (unsigned char)ch;//并记录到16个字符一行的缓冲区中
fprintf(fpw, "%02X ", (unsigned char)ch);//将该字符(1Byte,如'A')写到输出文件中(变成2Byte,'A'对应0X41)
num++;//读取的字符数加1
if(num % 16 == 0){//输出文件格式化,读取16个字节换一行
fprintf(fpw, "; ");
for(i = 0; i<STRING_BUFFER; i++){//解析缓冲区中的字符
if(strbuf[i] > 31 && strbuf[i] < 127)
fprintf(fpw, "%c", strbuf[i]);
else
fprintf(fpw, ".");
}
fprintf(fpw, "\n%08X: ", num);//换行
memset(strbuf, 0, STRING_BUFFER);//清空缓冲区
}
}
fclose(fpr);
fclose(fpw);
printf("Complete!\n");
return 0;
}
2、判断文件读取遇到EOF(0XFF)的原因是0X1A引起的还是到文件末尾引起的:
FILE * fp = fopen("file", "r");//以文本文件读取
fseek(fp, 0, SEEK_END);
const size_t len_file = ftell(fp);
fseek(fp, 0, SEEK_SET);
//获取文件长度后根据读取的字符个数来判断是否结束
同样是对上面所述文件进行读取:
#include "stdafx.h"
#define STRING_BUFFER 16
char strbuf[STRING_BUFFER] = {0};
int main(void)
{
unsigned int num = 0, i = 0;
FILE * fpr = fopen("F:\\new.dcm", "r");//以非二进制流读取
FILE * fpw = fopen("F:\\new.hex", "w");
if(fpr == NULL || fpw == NULL){
printf("open file failure at line:%d\n", __LINE__);
exit(EXIT_FAILURE);
}
//获取文件长度
fseek(fpr, 0, SEEK_END);
const unsigned int len_file = ftell(fpr);
fseek(fpr, 0, SEEK_SET);
printf("%d\n", len_file);
fprintf(fpw, "%08X: ", num);
//不可以用feof()判断,因为以文本形式读取时0X1A已经被解析成0XFF
while(num < len_file){//根据读取的字符数与文件长度来判断是否到达文件末尾
int ch = fgetc(fpr);
if((unsigned char)ch == 0XFF){//如果读取到0XFF,判断是否是0X1A所引起的
strbuf[num % STRING_BUFFER] = 0X1A;
fprintf(fpw, "1A ");
fseek(fpr, num+1, SEEK_SET);
//不能用fseek(fpr, 1, SEEK_CUR);或fseek(fpr, ftell(fpr)+1, SEEK_SET);
//因为如果是遇到结束符EOF或0X1A时,ftell()的值即SEEK_CUR会变成4096的倍数
}
else{
strbuf[num % STRING_BUFFER] = (unsigned char)ch;
fprintf(fpw, "%02X ", (unsigned char)ch);
}
num++;
if(num % 16 == 0){
fprintf(fpw, "; ");
for(i = 0; i<STRING_BUFFER; i++){
if(strbuf[i] > 31 && strbuf[i] < 127)
fprintf(fpw, "%c", strbuf[i]);
else
fprintf(fpw, ".");
}
fprintf(fpw, "\n%08X: ", num);
memset(strbuf, 0, STRING_BUFFER);
}
}
fclose(fpr);
fclose(fpw);
printf("Complete!\n");
return 0;
}
关于fgetc()返回值为何为int以及对于EOF引起的另外一种读取文件意外结束的情况,可以参考fgetc函数的返回值为什么是 int 类型。这两种意外结束不是一种情况,一个是逻辑不严谨导致的,一个就目前看来是微软系统库的问题。
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献5条内容
所有评论(0)