文本方式和二进制方式在读写文件时是有区别的,以下主要对Windows系统下的一些不同进行说明。
第一:
1、使用二进制方式进行读文件时,会原封不动的读出全部的内容,写文件的时候,会把内存缓冲区的内容原封不动的写到文件中。
2、使用文本方式进行读文件时,会将回车换行符号CRLF(0x0D OxOA)全部转换成单个的换行符号LF(OxOA),写文件的时候,会将换行符号LF( OxOA)全部转换成回车换行符号CRLF(0x0D OxOA)。
下面以写文件为例进行说明:
1)、以文本方式写文件,行尾加回车符:
FILE* fp = fopen("1.txt", "wt");//以文本方式写文件
if (fp)
{
for (int i = 0;i < 10;i++)
{
fprintf(fp,"%s%s\n","12","34");//行尾加回车符:\n
}
fclose(fp);
fp = NULL;
}
测试结果:
可知:在写文件时,\n (LF)转换成了 \r\n (CR LF)。
同理,如果我们在以文本方式写文件时,行尾加 回车、换行 符:
FILE* fp = fopen("1.txt", "wt");//以文本方式写文件
if (fp)
{
for (int i = 0;i < 10;i++)
{
fprintf(fp,"%s%s\r\n","12","34");//行尾加回车换行符:\r\n
}
fclose(fp);
fp = NULL;
}
测试结果:
结果表明:同样如此(注意多了一个空行)。
2)、以二进制方式进行写文件,行尾加 换行 符:
FILE* fp = fopen("1.txt", "wb");//以二进制方式写文件
if (fp)
{
for (int i = 0;i < 10;i++)
{
fprintf(fp,"%s%s\n","12","34");//行尾加换行符:\n
}
fclose(fp);
fp = NULL;
}
结果:
表明:内容原封不动的进行写入,没有像文本方式一样进行转换。
第二、基于上面第一点的区别,如果使用文本方式打开二进制文件,就很容易出现文件读取不完整、或是内容不对的错误。下面以文本方式和二进制方式分别读取一张图片进行验证:
原图:
1、以二进制方式进行读取,并写入:
DWORD dwFileSize = 0;
WIN32_FIND_DATA FileInfo;
ZeroMemory(&FileInfo,sizeof(WIN32_FIND_DATA));
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFile("D:\\12123.jpg",&FileInfo);
if(hFind != INVALID_HANDLE_VALUE)
{
dwFileSize = FileInfo.nFileSizeLow ;
}
FindClose(hFind);
BYTE* buffer = new BYTE[dwFileSize];
if (buffer == NULL)
{
cout<<"Create buffer error !"<<endl;
return 0;
}
ZeroMemory(buffer,dwFileSize);
FILE *f = NULL;
fopen_s(&f,"D:\\12123.jpg","r+b");
if (f == NULL)
{
delete [] buffer;
buffer = NULL;
cout<<"fopen_s error -1 !"<<endl;
return 0;
}
else
{
fread(buffer,dwFileSize,1,f);
}
fclose(f);
f = NULL;
fopen_s(&f,"D:\\3.jpg","w+b");
if (f == NULL)
{
cout<<"fopen_s error -2 !"<<endl;
return 0;
}
if (fwrite(buffer,dwFileSize,1,f) < 1){
cout<<"fwrite error !"<<endl;
}
fclose(f);
f = NULL;
结果如下:
内容原封不动,和原图一样。
2、以文本形式读入文件,并写入:
DWORD dwFileSize = 0;
WIN32_FIND_DATA FileInfo;
ZeroMemory(&FileInfo,sizeof(WIN32_FIND_DATA));
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFile("D:\\12123.jpg",&FileInfo);
if(hFind != INVALID_HANDLE_VALUE)
{
dwFileSize = FileInfo.nFileSizeLow ;
}
FindClose(hFind);
BYTE* buffer = new BYTE[dwFileSize];
if (buffer == NULL)
{
cout<<"Create buffer error !"<<endl;
return 0;
}
ZeroMemory(buffer,dwFileSize);
FILE *f = NULL;
fopen_s(&f,"D:\\12123.jpg","r+t");
if (f == NULL)
{
delete [] buffer;
buffer = NULL;
cout<<"fopen_s error -1 !"<<endl;
return 0;
}
else
{
fread(buffer,dwFileSize,1,f);
}
fclose(f);
f = NULL;
fopen_s(&f,"D:\\3.jpg","w+t");
if (f == NULL)
{
cout<<"fopen_s error -2 !"<<endl;
return 0;
}
if (fwrite(buffer,dwFileSize,1,f) < 1){
cout<<"fwrite error !"<<endl;
}
fclose(f);
f = NULL;
结果出现错误:
因此,在windos平台下开发中,以二进制模式创建并写入的文件,在读取时,为了防止读文件出错,建议以二进制模式进行读取;同样的道理,以文本模式创建并写入的文件,在读取该文件时,建议以文本模式进行读取。
附上一些常用的文件读写函数,开发时可以自行选择合适的来用:
fprintf/fscanf 、 fgets/fputs 、 fgetc/fputc 、 fwrite/fread 等