被fread的返回值整了

剛纔編一個關於用C庫函數實現的文件複製操做的代碼時發生錯誤。錯誤的根本是想固然的覺得fread函數的用法,對其理解不深入。後來在網友幫助下才發現錯誤。函數

其實函數的用法能夠經過Linux中的man來得到幫助。ui

好比fread.在終端鍵入指針

man 3 fread
這是會出現下面的東西:

NAME
       fread, fwrite - binary stream input/output

SYNOPSIS
       #include <stdio.h>

       size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

       size_t fwrite(const void *ptr, size_t size, size_t nmemb,
                     FILE *stream);

DESCRIPTION
       The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.

       The  function  fwrite()  writes  nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by
       ptr.

       For nonlocking counterparts, see unlocked_stdio(3).

RETURN VALUE
       On success, fread() and fwrite() return the number of items read or written.  This number equals the number of bytes transferred only when size is 1.  If an
       error occurs, or the end of the file is reached, the return value is a short item count (or zero).

       fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.

重點放在對返回值。

能夠看出,若是調用成功的話,函數會返回讀到的元素個數。若是想返回實際讀取的字節數的話只有當size=1,也就是第二個參數size爲1時。若是發生讀取錯誤的話,或者已經到達文件末尾,返回值是一個小的元素個數值或者是0.下面給出個人代碼,正確實現文件拷貝的代碼,以此分析。code

#include <stdio.h>

#define BUFFER_SIZE  1024

int main(int argc, char *argv[])
{
	FILE *from_fp, *to_fp;
	int bytes_read, bytes_write;
	char *ptr;
	char buffer[BUFFER_SIZE];

	if(argc != 3)		//參數包括源文件名與目標文件名
	{
		printf("Input failed!\n");
		return 1;
	}

	if( (from_fp = fopen(argv[1],"r")) == NULL )	//以只讀方式打開源文件名
	{
		printf("File is not exist\n");
		return 1;
	}
	
	if((to_fp = fopen(argv[2],"w+")) == NULL)	   //打開第二個文件
	{
		printf("Open file failed!\n");	
		return 1;
	}

	while(bytes_read = fread(buffer, 1, BUFFER_SIZE, from_fp))	//讀取BUFFSIZE大小字節
	{
		if(bytes_read > 0)			//讀取有效數據
		{
			ptr = buffer;
			while(bytes_write = fwrite(ptr, 1, bytes_read, to_fp))	//寫數據到目標文件
			{
				if(bytes_write == bytes_read)			//寫完	
					break;
				else if(bytes_write > 0)			//未寫完
				{
					ptr += bytes_write;
					bytes_read -= bytes_write;
				}
			}
			if(bytes_write == 0)			//寫錯誤
				break;
		}
	}
	
	fclose(from_fp);
	fclose(to_fp);

	return 0;
}

注意到個人fread和fwrite中的第二個參數size都是1,這樣的話我返回值就是實際讀取到的或寫入的字節數。剛開始我寫的程序不是這樣的,我是

while(bytes_read = fread(buffer, BUFFER_SIZE, 1,from_fp))
while(bytes_write = fwrite(ptr, bytes_read, 1, to_fp))

這裏第三個參數爲1,換句話說,也就是說要讀取1個元素,此元素中包含BUFFER_SIZE個字節,由於個人文件不知足這個條件,這樣的元素值不存在。因而返回的值爲0,這也是爲何個人文件數據沒有複製到另外一個文件的緣由了,由於根本就沒有執行這個循環中的代碼。element

另一個須要注意到的問題是fread函數不能區分文件是否結尾和出錯兩種狀況。因此必須使用ferror()和feof()函數來肯定究竟是哪一種狀況,因此關於文件複製還有下面另外一種寫法。代碼以下:input

#include <stdio.h>
#include <string.h>

#define BUFFER_SIZE  1024

int main(int argc, char *argv[])
{
	FILE *from_fp, *to_fp;
	//int bytes_read, bytes_write;
	long file_len = 0;
	char buffer[BUFFER_SIZE];

	if(argc != 3)		//參數包括源文件名與目標文件名
	{
		printf("Input failed!\n");
		return 1;
	}

	if( (from_fp = fopen(argv[1],"r")) == NULL )	//以只讀方式打開源文件名
	{
		printf("File is not exist\n");
		return 1;
	}
	
	if((to_fp = fopen(argv[2],"w+")) == NULL)	   //打開第二個文件
	{
		printf("Open file failed!\n");	
		return 1;
	}
	
	fseek(from_fp, 0L, SEEK_END);		//定位文件指針到尾部
	file_len = ftell(from_fp);			//得到文件長度
	fseek(from_fp, 0L, SEEK_SET);		//定位文件指針到開始處

	while(!feof(from_fp))				//判斷文件是否結束
	{
		fread(buffer, BUFFER_SIZE, 1, from_fp);
		if(BUFFER_SIZE > file_len)				//緩衝區長度大於文件長度
			fwrite(buffer, file_len, 1, to_fp);
		else								
		{
			fwrite(buffer, BUFFER_SIZE, 1, to_fp);
			file_len -= BUFFER_SIZE;
		}
		bzero(buffer,BUFFER_SIZE);		//清零緩衝區
	}

	fclose(from_fp);
	fclose(to_fp);

	return 0;
}
這裏面多了幾個函數,其中feof就是用來檢測文件是否結尾的函數。其返回值非0時表示文件結束。還有一個函數bzero是清零一段緩衝區的函數,使用需包含頭文件string.h。注意fread和fwrite函數的書寫就是採用第三個參數爲1的方式來書寫的了。
相關文章
相關標籤/搜索