fopen等:文本方式和二进制方式打开文件的区别

文本方式和二进制方式在读写文件时是有区别的,以下主要对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 等

发布了415 篇原创文章 · 获赞 123 · 访问量 64万+

猜你喜欢

转载自blog.csdn.net/u012372584/article/details/77836168