日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

fread函数和fwrite函数,read,write

發(fā)布時(shí)間:2023/12/10 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 fread函数和fwrite函数,read,write 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

fread函數(shù)和fwrite函數(shù)

?1.函數(shù)功能

? 用來(lái)讀寫一個(gè)數(shù)據(jù)塊

2.一般調(diào)用形式

? fread(buffer,size,count,fp);

? fwrite(buffer,size,count,fp);

3.說(shuō)明

? (1)buffer:是一個(gè)指針,對(duì)fread來(lái)說(shuō),它是讀入數(shù)據(jù)的存放地址。對(duì)fwrite來(lái)說(shuō),是要輸出數(shù)據(jù)的地址

? (2)size:要讀寫的字節(jié)數(shù)

? (3)count:要進(jìn)行讀寫多少個(gè)size字節(jié)的數(shù)據(jù)項(xiàng);// 1代表二進(jìn)制

? (4)fp:文件型指針。

?注意:

????????? 1 完成次寫操(fwrite())作后必須關(guān)閉流(fclose());

?????????? 2 完成一次讀操作(fread())后,如果沒(méi)有關(guān)閉流(fclose()),則指針(FILE * fp)自動(dòng)向后移動(dòng)前一次讀寫的長(zhǎng)度,不關(guān)閉流繼續(xù)下一次讀操作則接著上次的輸出繼續(xù)輸出;

?????????? 3 fprintf() : 按格式輸入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不過(guò)不是寫到控制臺(tái),而是寫到流罷了。注意的是返回值為此次操作寫入到文件的字節(jié)數(shù)。如int c = fprintf(fp, "%s %s %d %f", str1,str2, a, b) ;str1:10字節(jié);str2: 10字節(jié);a:2字節(jié);b:8字節(jié),c為33,因?yàn)閷懭霑r(shí)不同的數(shù)據(jù)間自動(dòng)加入一個(gè)空格。

文件使用之后一定要關(guān)閉,否則將不能正確顯示內(nèi)容.fwrite:讀入兩個(gè)學(xué)生信息然后用fwrite存入文件

fread:用fread從文件中讀出學(xué)生信息。

fwrite.c

#include <stdio.h>
#define SIZE 2
struct student_type
{
?char name[10];
?int num;
?int age;
?char addr[10];
}stud[SIZE];
void save()
{
?FILE *fp;
?int i;
?if((fp=fopen("stu_list","wb"))==NULL)
?{
? printf("cant open the file");
? exit(0);
?}
?for(i=0;i<SIZE;i++)
?{
?? if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1)
??? printf("file write error\n");
?}
?fclose(fp);
}
main()
{
?int i;
?for(i=0;i<SIZE;i++)
?{
?? scanf("%s%d%d%s",&stud[i].name,&stud[i].num,&stud[i].age,&stud[i].addr);
?? save();
?}
?for(i=0;i<SIZE;i++)
?{
?? printf("%s,%d,%d",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
?}
}

fread.c

#include <stdio.h>
#define SIZE 2
struct student_type
{
?char name[10];
?int num;
?int age;
?char addr[10];
}stud[SIZE];
void read()
{
?FILE *fp;
?int i;
?if((fp=fopen("stu_list","rb"))==NULL)
?{
? printf("cant open the file");
? exit(0);
?}
?for(i=0;i<SIZE;i++)
?{
?? if(fread(&stud[i],sizeof(struct student_type),1,fp)!=1)
??? printf("file write error\n");
?}
?fclose(fp);
}
main()
{

?int i;
?read();
?for(i=0;i<SIZE;i++)
?{
?? printf("%s,%d,%d,%s",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
?? printf("\n");
?}
}

在C語(yǔ)言中進(jìn)行文件操作時(shí),我們經(jīng)常用到fread()和fwrite(),用它們來(lái)對(duì)文件進(jìn)行讀寫操作。下面詳細(xì)紹一下這兩個(gè)函數(shù)的用法。

? 我們?cè)谟肅語(yǔ)言編寫程序時(shí),一般使用標(biāo)準(zhǔn)文件系統(tǒng),即緩沖文件系統(tǒng)。系統(tǒng)在內(nèi)存中為每個(gè)正在讀寫的文件開(kāi)辟“文件緩沖區(qū)”,在對(duì)文件進(jìn)行讀寫時(shí)數(shù)據(jù)都經(jīng)過(guò)緩沖區(qū)。要對(duì)文件進(jìn)行讀寫,系統(tǒng)首先開(kāi)辟一塊內(nèi)存區(qū)來(lái)保存文件信息,保存這些信息用的是一個(gè)結(jié)構(gòu)體,將這個(gè)結(jié)構(gòu)體typedef為FILE類型。我們首先要定義一個(gè)指向這個(gè)結(jié)構(gòu)體的指針,當(dāng)程序打開(kāi)一個(gè)文件時(shí),我們獲得指向FILE結(jié)構(gòu)的指針,通過(guò)這個(gè)指針,我們就可以對(duì)文件進(jìn)行操作。例如:

#i nclude <stdio.h>

#i nclude <string.h>

int main()

{

?? FILE *fp;

?? char buffer[100] = "This is a test";

?? if((fp = fopen("c:\\example.txt", "w")) == 0)

??? {

?????? printf("open failed!");

?????? exit(1);

??? }

?? fwrite(buffer, 1, strlen("This is a test"), fp);

?? fclose(fp);

?? return 0;

}

? 通過(guò)以上代碼,我們就在c盤的根目錄下建立了一個(gè)名為example擴(kuò)展名為.txt的文件,我們打開(kāi)可以看到上面寫上了This is a test。當(dāng)我們對(duì)它將它讀出時(shí),用如下代碼:

#i nclude <stdio.h>

#i nclude <mem.h>

int main()

{

?? FILE *fp;?? int len;

?? char buffer[100];

?? /*memset(buffer, 1, 100); */

?? if((fp = fopen("c:\\example.txt", "r")) == 0)

??? {

?????? printf("open failed!");

?????? exit(1);

??? }

?? fseek(fp, 0L, SEEK_END);

?? len = ftell(fp);

?? rewind(fp);

?? fread(buffer, 1, len , fp);

?? printf("%s",buffer);

?? fclose(fp);

?? getch();

?? return 0;

}

?可以看到,當(dāng)我們使用memset了以后,讀出了一大堆亂碼,這是為什么呢?原因是我們?cè)趂write函數(shù)時(shí)寫入的字節(jié)數(shù)是用strlen求得的,也就是說(shuō)字符串最后的'\0'并沒(méi)有寫到文件中去。所以我們從文件中讀到buffer中時(shí)也自然沒(méi)有'\0',因?yàn)閎uffer中的數(shù)是隨機(jī)的,除非buffer中最后一個(gè)字符的下一個(gè)數(shù)恰好隨機(jī)到0(可能性很小,這里用memset將它排除),否則以%s將buffer中的字符輸出時(shí)遇不到0,所以亂碼產(chǎn)生。解決的辦法有很多,你可以在向文件寫數(shù)據(jù)時(shí)多寫入一個(gè)字節(jié),系統(tǒng)會(huì)自動(dòng)寫入0,fwrite(buffer, 1, strlen("This is a test")+1, fp);這樣讀出時(shí)最后就有一個(gè)0了。或者讀出操作完成后,在最后一個(gè)字符后面補(bǔ)上一個(gè)0:buffer[len] = 0;這樣問(wèn)題也可得到解決。
?
fread函數(shù)和fwrite函數(shù) 1.函數(shù)功能

? 用來(lái)讀寫一個(gè)數(shù)據(jù)塊。

2.一般調(diào)用形式

? fread(buffer,size,count,fp);

? fwrite(buffer,size,count,fp);

3.說(shuō)明

? (1)buffer:是一個(gè)指針,對(duì)fread來(lái)說(shuō),它是讀入數(shù)據(jù)的存放地址。對(duì)fwrite來(lái)說(shuō),是要輸出數(shù)據(jù)的地址。

? (2)size:要讀寫的字節(jié)數(shù);

? (3)count:要進(jìn)行讀寫多少個(gè)size字節(jié)的數(shù)據(jù)項(xiàng);

? (4)fp:文件型指針。

?注意:1 完成次寫操(fwrite())作后必須關(guān)閉流(fclose());

?????????? 2 完成一次讀操作(fread())后,如果沒(méi)有關(guān)閉流(fclose()),則指針(FILE * fp)自動(dòng)向后移動(dòng)前一次讀寫的長(zhǎng)度,不關(guān)閉流繼續(xù)下一次讀操作則接著上次的輸出繼續(xù)輸出;

?????????? 3 fprintf() : 按格式輸入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不過(guò)不是寫到控制臺(tái),而是寫到流罷了。注意的是返回值為此次操作寫入到文件的字節(jié)數(shù)。如int c = fprintf(fp, "%s %s %d %f", str1,str2, a, b) ;str1:10字節(jié);str2: 10字節(jié);a:2字節(jié);b:8字節(jié),c為33,因?yàn)閷懭霑r(shí)不同的數(shù)據(jù)間自動(dòng)加入一個(gè)空格。

文件使用之后一定要關(guān)閉,否則將不能正確顯示內(nèi)容.fwrite:讀入兩個(gè)學(xué)生信息然后用fwrite存入文件

fread:用fread從文件中讀出學(xué)生信息。

fwrite.c

#include <stdio.h>
#define SIZE 2
struct student_type
{
?char name[10];
?int num;
?int age;
?char addr[10];
}stud[SIZE];
void save()
{
?FILE *fp;
?int i;
?if((fp=fopen("stu_list","wb"))==NULL)
?{
? printf("cant open the file");
? exit(0);
?}
?for(i=0;i<SIZE;i++)
?{
?? if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1)
??? printf("file write error\n");
?}
?fclose(fp);
}
main()
{
?int i;
?for(i=0;i<SIZE;i++)
?{
?? scanf("%s%d%d%s",&stud[i].name,&stud[i].num,&stud[i].age,&stud[i].addr);
?? save();
?}
?for(i=0;i<SIZE;i++)
?{
?? printf("%s,%d,%d",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
?}
}

fread.c

#include <stdio.h>
#define SIZE 2
struct student_type
{
?char name[10];
?int num;
?int age;
?char addr[10];
}stud[SIZE];
void read()
{
?FILE *fp;
?int i;
?if((fp=fopen("stu_list","rb"))==NULL)
?{
? printf("cant open the file");
? exit(0);
?}
?for(i=0;i<SIZE;i++)
?{
?? if(fread(&stud[i],sizeof(struct student_type),1,fp)!=1)
??? printf("file write error\n");
?}
?fclose(fp);
}
main()
{

?int i;
?read();
?for(i=0;i<SIZE;i++)
?{
?? printf("%s,%d,%d,%s",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
?? printf("\n");
?}
}

在C語(yǔ)言中進(jìn)行文件操作時(shí),我們經(jīng)常用到fread()和fwrite(),用它們來(lái)對(duì)文件進(jìn)行讀寫操作。下面詳細(xì)紹一下這兩個(gè)函數(shù)的用法。

? 我們?cè)谟肅語(yǔ)言編寫程序時(shí),一般使用標(biāo)準(zhǔn)文件系統(tǒng),即緩沖文件系統(tǒng)。系統(tǒng)在內(nèi)存中為每個(gè)正在讀寫的文件開(kāi)辟“文件緩沖區(qū)”,在對(duì)文件進(jìn)行讀寫時(shí)數(shù)據(jù)都經(jīng)過(guò)緩沖區(qū)。要對(duì)文件進(jìn)行讀寫,系統(tǒng)首先開(kāi)辟一塊內(nèi)存區(qū)來(lái)保存文件信息,保存這些信息用的是一個(gè)結(jié)構(gòu)體,將這個(gè)結(jié)構(gòu)體typedef為FILE類型。我們首先要定義一個(gè)指向這個(gè)結(jié)構(gòu)體的指針,當(dāng)程序打開(kāi)一個(gè)文件時(shí),我們獲得指向FILE結(jié)構(gòu)的指針,通過(guò)這個(gè)指針,我們就可以對(duì)文件進(jìn)行操作。例如:

#i nclude <stdio.h>

#i nclude <string.h>

int main()

{

?? FILE *fp;

?? char buffer[100] = "This is a test";

?? if((fp = fopen("c:\\example.txt", "w")) == 0)

??? {

?????? printf("open failed!");

?????? exit(1);

??? }

?? fwrite(buffer, 1, strlen("This is a test"), fp);

?? fclose(fp);

?? return 0;

}

? 通過(guò)以上代碼,我們就在c盤的根目錄下建立了一個(gè)名為example擴(kuò)展名為.txt的文件,我們打開(kāi)可以看到上面寫上了This is a test。當(dāng)我們對(duì)它將它讀出時(shí),用如下代碼:

#i nclude <stdio.h>

#i nclude <mem.h>

int main()

{

?? FILE *fp;?? int len;

?? char buffer[100];

?? /*memset(buffer, 1, 100); */

?? if((fp = fopen("c:\\example.txt", "r")) == 0)

??? {

?????? printf("open failed!");

?????? exit(1);

??? }

?? fseek(fp, 0L, SEEK_END);

?? len = ftell(fp);

?? rewind(fp);

?? fread(buffer, 1, len , fp);

?? printf("%s",buffer);

?? fclose(fp);

?? getch();

?? return 0;

}

?可以看到,當(dāng)我們使用memset了以后,讀出了一大堆亂碼,這是為什么呢?原因是我們?cè)趂write函數(shù)時(shí)寫入的字節(jié)數(shù)是用strlen求得的,也就是說(shuō)字符串最后的'\0'并沒(méi)有寫到文件中去。所以我們從文件中讀到buffer中時(shí)也自然沒(méi)有'\0',因?yàn)閎uffer中的數(shù)是隨機(jī)的,除非buffer中最后一個(gè)字符的下一個(gè)數(shù)恰好隨機(jī)到0(可能性很小,這里用memset將它排除),否則以%s將buffer中的字符輸出時(shí)遇不到0,所以亂碼產(chǎn)生。解決的辦法有很多,你可以在向文件寫數(shù)據(jù)時(shí)多寫入一個(gè)字節(jié),系統(tǒng)會(huì)自動(dòng)寫入0,fwrite(buffer, 1, strlen("This is a test")+1, fp);這樣讀出時(shí)最后就有一個(gè)0了。或者讀出操作完成后,在最后一個(gè)字符后面補(bǔ)上一個(gè)0:buffer[len] = 0;這樣問(wèn)題也可得到解決。
?

?
?
?
?
/***
*fwrite.c - read from a stream
*
*?????? Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*?????? Write to the specified stream from the user's buffer.
*
*******************************************************************************/

#include <cruntime.h>
#include <stdio.h>
#include <mtdll.h>
#include <io.h>
#include <string.h>
#include <file2.h>
#include <internal.h>

/***
*size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream) -
*?????? write to the specified stream from the specified buffer.
*
*Purpose:
*?????? Write 'count' items of size 'size' to the specified stream from
*?????? the specified buffer. Return when 'count' items have been written
*?????? or no more items can be written to the stream.
*
*Entry:
*?????? buffer? - pointer to user's buffer
*?????? size??? - size of the item to write
*?????? count?? - number of items to write
*?????? stream? - stream to write to
*
*Exit:
*?????? Returns the number of (whole) items that were written to the stream.
*?????? This may be less than 'count' if an error or eof occurred. In this
*?????? case, ferror() or feof() should be used to distinguish between the
*?????? two conditions.
*
*Notes:
*?????? fwrite will attempt to buffer the stream (side effect of the _flsbuf
*?????? call) if necessary.
*
*?????? No more than 0xFFFE bytes may be written out at a time by a call to
*?????? write(). Further, write() does not handle huge buffers. Therefore,
*?????? in large data models, the write request is broken down into chunks
*?????? that do not violate these considerations. Each of these chunks is
*?????? processed much like an fwrite() call in a small data model (by a
*?????? call to _nfwrite()).
*
*?????? This code depends on _iob[] being a near array.
*
*?????? MTHREAD/DLL - Handled in just two layers since it is small data
*?????? model. The outer layer, fwrite(), handles stream locking/unlocking
*?????? and calls _fwrite_lk() to do the work. _fwrite_lk() is the same as
*?????? the single-thread, small data model version of fwrite().
*
*******************************************************************************/


#ifdef _MT
/* define locking/unlocking version */
size_t __cdecl fwrite (
??????? const void *buffer,
??????? size_t size,
??????? size_t count,
??????? FILE *stream
??????? )
{
??????? size_t retval;

??????? _lock_str(stream);????????????????????? /* lock stream */
??????? retval = _fwrite_lk(buffer, size, count, stream);? /* do the read */
??????? _unlock_str(stream);??????????????????? /* unlock stream */
??????? return retval;
}
#endif? /* _MT */

/* define the normal version */
#ifdef _MT
size_t __cdecl _fwrite_lk (
#else? /* _MT */
size_t __cdecl fwrite (
#endif? /* _MT */
??????? const void *buffer,
??????? size_t size,
??????? size_t num,
??????? FILE *stream
??????? )
{
??????? const char *data;?????????????? /* point to where data comes from next */
??????? unsigned total;???????????????? /* total bytes to write */
??????? unsigned count;???????????????? /* num bytes left to write */
??????? unsigned bufsize;?????????????? /* size of stream buffer */
??????? unsigned nbytes;??????????????? /* number of bytes to write now */
??????? unsigned nwritten;????????????? /* number of bytes written */
??????? int c;????????????????????????? /* a temp char */

??????? /* initialize local vars */
??????? data = buffer;
??????? count = total = size * num;
??????? if (0 == count)
??????????? return 0;

??????? if (anybuf(stream))
??????????????? /* already has buffer, use its size */
??????????????? bufsize = stream->_bufsiz;
??????? else
#if defined (_M_M68K) || defined (_M_MPPC)
??????????????? /* assume will get BUFSIZ buffer */
??????????????? bufsize = BUFSIZ;
#else? /* defined (_M_M68K) || defined (_M_MPPC) */
??????????????? /* assume will get _INTERNAL_BUFSIZ buffer */
??????????????? bufsize = _INTERNAL_BUFSIZ;
#endif? /* defined (_M_M68K) || defined (_M_MPPC) */

??????? /* here is the main loop -- we go through here until we're done */
??????? while (count != 0) {
??????????????? /* if the buffer is big and has room, copy data to buffer */
??????????????? if (bigbuf(stream) && stream->_cnt != 0) {
??????????????????????? /* how much do we want? */
??????????????????????? nbytes = (count < (unsigned)stream->_cnt) ? count : stream->_cnt;
??????????????????????? memcpy(stream->_ptr, data, nbytes);

??????????????????????? /* update stream and amt of data written */
??????????????????????? count -= nbytes;
??????????????????????? stream->_cnt -= nbytes;
??????????????????????? stream->_ptr += nbytes;
??????????????????????? data += nbytes;
??????????????? }
??????????????? else if (count >= bufsize) {
??????????????????????? /* If we have more than bufsize chars to write, write
?????????????????????????? data by calling write with an integral number of
?????????????????????????? bufsiz blocks.? If we reach here and we have a big
?????????????????????????? buffer, it must be full so _flush it. */

??????????????????????? if (bigbuf(stream)) {
??????????????????????????????? if (_flush(stream)) {
??????????????????????????????????????? /* error, stream flags set -- we're out
?????????????????????????????????????????? of here */
??????????????????????????????????????? return (total - count) / size;
??????????????????????????????? }
??????????????????????? }

??????????????????????? /* calc chars to read -- (count/bufsize) * bufsize */
??????????????????????? nbytes = ( bufsize ? (count - count % bufsize) :
?????????????????????????????????? count );

??????????????????????? nwritten = _write(_fileno(stream), data, nbytes);
??????????????????????? if (nwritten == (unsigned)EOF) {
??????????????????????????????? /* error -- out of here */
??????????????????????????????? stream->_flag |= _IOERR;
??????????????????????????????? return (total - count) / size;
??????????????????????? }

??????????????????????? /* update count and data to reflect write */

??????????????????????? count -= nwritten;
??????????????????????? data += nwritten;

??????????????????????? if (nwritten < nbytes) {
??????????????????????????????? /* error -- out of here */
??????????????????????????????? stream->_flag |= _IOERR;
??????????????????????????????? return (total - count) / size;
??????????????????????? }
??????????????? }
??????????????? else {
??????????????????????? /* buffer full and not enough chars to do direct write,
?????????????????????????? so do a _flsbuf. */
??????????????????????? c = *data;? /* _flsbuf write one char, this is it */
??????????????????????? if (_flsbuf(c, stream) == EOF) {
??????????????????????????????? /* error or eof, stream flags set by _flsbuf */
??????????????????????????????? return (total - count) / size;
??????????????????????? }

??????????????????????? /* _flsbuf wrote a char -- update count */
??????????????????????? ++data;
??????????????????????? --count;

??????????????????????? /* update buffer size */
??????????????????????? bufsize = stream->_bufsiz > 0 ? stream->_bufsiz : 1;
??????????????? }
??????? }

??????? /* we finished successfully, so just return num */
??????? return num;
}


這是fread的源文件

/***
*fread.c - read from a stream
*
*?????? Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*?????? Read from the specified stream into the user's buffer.
*
*******************************************************************************/

#include <cruntime.h>
#include <stdio.h>
#include <mtdll.h>
#include <io.h>
#include <string.h>
#include <file2.h>

/***
*size_t fread(void *buffer, size_t size, size_t count, FILE *stream) -
*?????? read from specified stream into the specified buffer.
*
*Purpose:
*?????? Read 'count' items of size 'size' from the specified stream into
*?????? the specified buffer. Return when 'count' items have been read in
*?????? or no more items can be read from the stream.
*
*Entry:
*?????? buffer? - pointer to user's buffer
*?????? size??? - size of the item to read in
*?????? count?? - number of items to read
*?????? stream? - stream to read from
*
*Exit:
*?????? Returns the number of (whole) items that were read into the buffer.
*?????? This may be less than 'count' if an error or eof occurred. In this
*?????? case, ferror() or feof() should be used to distinguish between the
*?????? two conditions.
*
*Notes:
*?????? fread will attempt to buffer the stream (side effect of the _filbuf
*?????? call) if necessary.
*
*?????? No more than 0xFFFE bytes may be read in at a time by a call to
*?????? read(). Further, read() does not handle huge buffers. Therefore,
*?????? in large data models, the read request is broken down into chunks
*?????? that do not violate these considerations. Each of these chunks is
*?????? processed much like an fread() call in a small data model (by a
*?????? call to _nfread()).
*
*?????? MTHREAD/DLL - Handled in three layers. fread() handles the locking
*?????? and DS saving/loading/restoring (if required) and calls _fread_lk()
*?????? to do the work. _fread_lk() is the same as the single-thread,
*?????? large data model version of fread(). It breaks up the read request
*?????? into digestible chunks and calls _nfread() to do the actual work.
*
*?????? 386/MTHREAD/DLL - Handled in just the two layers since it is small
*?????? data model. The outer layer, fread(), takes care of the stream locking
*?????? and calls _fread_lk() to do the actual work. _fread_lk() is the same
*?????? as the single-thread version of fread().
*
*******************************************************************************/


#ifdef _MT
/* define locking/unlocking version */
size_t __cdecl fread (
??????? void *buffer,
??????? size_t size,
??????? size_t count,
??????? FILE *stream
??????? )
{
??????? size_t retval;

??????? _lock_str(stream);??????????????????????????????? /* lock stream */
??????? retval = _fread_lk(buffer, size, count, stream);? /* do the read */
??????? _unlock_str(stream);????????????????????????????? /* unlock stream */
??????? return retval;
}
#endif? /* _MT */

/* define the normal version */
#ifdef _MT
size_t __cdecl _fread_lk (
#else? /* _MT */
size_t __cdecl fread (
#endif? /* _MT */
??????? void *buffer,
??????? size_t size,
??????? size_t num,
??????? FILE *stream
??????? )
{
??????? char *data;???????????????????? /* point to where should be read next */
??????? unsigned total;???????????????? /* total bytes to read */
??????? unsigned count;???????????????? /* num bytes left to read */
??????? unsigned bufsize;?????????????? /* size of stream buffer */
??????? unsigned nbytes;??????????????? /* how much to read now */
??????? unsigned nread;???????????????? /* how much we did read */
??????? int c;????????????????????????? /* a temp char */

??????? /* initialize local vars */
??????? data = buffer;

??????? if ( (count = total = size * num) == 0 )
??????????????? return 0;

??????? if (anybuf(stream))
??????????????? /* already has buffer, use its size */
??????????????? bufsize = stream->_bufsiz;
??????? else
#if defined (_M_M68K) || defined (_M_MPPC)
??????????????? /* assume will get BUFSIZ buffer */
??????????????? bufsize = BUFSIZ;
#else? /* defined (_M_M68K) || defined (_M_MPPC) */
??????????????? /* assume will get _INTERNAL_BUFSIZ buffer */
??????????????? bufsize = _INTERNAL_BUFSIZ;
#endif? /* defined (_M_M68K) || defined (_M_MPPC) */

??????? /* here is the main loop -- we go through here until we're done */
??????? while (count != 0) {
??????????????? /* if the buffer exists and has characters, copy them to user
?????????????????? buffer */
??????????????? if (anybuf(stream) && stream->_cnt != 0) {
??????????????????????? /* how much do we want? */
??????????????????????? nbytes = (count < (unsigned)stream->_cnt) ? count : stream->_cnt;
??????????????????????? memcpy(data, stream->_ptr, nbytes);

??????????????????????? /* update stream and amt of data read */
??????????????????????? count -= nbytes;
??????????????????????? stream->_cnt -= nbytes;
??????????????????????? stream->_ptr += nbytes;
??????????????????????? data += nbytes;
??????????????? }
??????????????? else if (count >= bufsize) {
??????????????????????? /* If we have more than bufsize chars to read, get data
?????????????????????????? by calling read with an integral number of bufsiz
?????????????????????????? blocks.? Note that if the stream is text mode, read
?????????????????????????? will return less chars than we ordered. */

??????????????????????? /* calc chars to read -- (count/bufsize) * bufsize */
??????????????????????? nbytes = ( bufsize ? (count - count % bufsize) :
?????????????????????????????????? count );

??????????????????????? nread = _read(_fileno(stream), data, nbytes);
??????????????????????? if (nread == 0) {
??????????????????????????????? /* end of file -- out of here */
??????????????????????????????? stream->_flag |= _IOEOF;
??????????????????????????????? return (total - count) / size;
??????????????????????? }
??????????????????????? else if (nread == (unsigned)-1) {
??????????????????????????????? /* error -- out of here */
??????????????????????????????? stream->_flag |= _IOERR;
??????????????????????????????? return (total - count) / size;
??????????????????????? }

??????????????????????? /* update count and data to reflect read */
??????????????????????? count -= nread;
??????????????????????? data += nread;
??????????????? }
??????????????? else {
??????????????????????? /* less than bufsize chars to read, so call _filbuf to
?????????????????????????? fill buffer */
??????????????????????? if ((c = _filbuf(stream)) == EOF) {
??????????????????????????????? /* error or eof, stream flags set by _filbuf */
??????????????????????????????? return (total - count) / size;
??????????????????????? }

??????????????????????? /* _filbuf returned a char -- store it */
??????????????????????? *data++ = (char) c;
??????????????????????? --count;

??????????????????????? /* update buffer size */
??????????????????????? bufsize = stream->_bufsiz;
??????????????? }
??????? }

??????? /* we finished successfully, so just return num */
??????? return num;
} 贊同0| 評(píng)論????????????? 2009-7-29 20:06 zawdd | 七級(jí)
stdio.h
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
把數(shù)據(jù)寫入一個(gè)數(shù)據(jù)流
這個(gè)例子中實(shí)現(xiàn)了把從A到Z的26個(gè)字符寫入文件sample.txt:????
FILE *Stream;
int Count;?
char Buffer[30];??
Stream=fopen("sample.txt","w+t");??
Buffer[0]='A';?
for(I=1; I<=25;I++) {
? Buffer[I]=Buffer[I-1]+1;
}
? Count= fwrite(Buffer,sizeof(char),26,Stream);?
? cout<<Count;
? fclose(Stream);

fread
stdio.h
從一個(gè)數(shù)據(jù)流中讀取數(shù)據(jù)
使用實(shí)例:請(qǐng)參看feof函數(shù)
feof
stdio.h
int feof( FILE *stream );
測(cè)試文件指針是否指向數(shù)據(jù)流的尾部,若是則返回0,否則返回-1
這個(gè)例子中打開(kāi)文件sample.txt,每次讀取10個(gè)字節(jié),直到所以的字節(jié)被讀完為止:
??? FILE? *p;
??? int count,Size=0;
??? char Buffer[10];
??? if((p = fopen("sample.txt","r"))==NULL) exit(1);
??? while(!feof(p)) {
??????? count =fread (Buffer,sizeof(char),10,p);
??????? if(ferror(p)) {
??????????? perror("出錯(cuò)!");
??????????? break;
??????? }
??????? Size = Size + count;
??? }
??? fclose(p);

?

?

?

?

read函數(shù)從打開(kāi)的設(shè)備或文件中讀取數(shù)據(jù)。

#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);

返回值:成功返回讀取的字節(jié)數(shù),出錯(cuò)返回-1并設(shè)置errno如果在調(diào)read之前已到達(dá)文件末尾,則這次read返回0
?

參數(shù)count是請(qǐng)求讀取的字節(jié)數(shù),讀上來(lái)的數(shù)據(jù)保存在緩沖區(qū)buf,同時(shí)文件的當(dāng)前讀寫位置向后移。注意這個(gè)讀寫位置和使用C標(biāo)準(zhǔn)I/O庫(kù)時(shí)的讀寫位置有可能不同,這個(gè)讀寫位置是記在內(nèi)核中的,而使用C標(biāo)準(zhǔn)I/O庫(kù)時(shí)的讀寫位置是用戶空間I/O緩沖區(qū)中的位置。比如用fgetc讀一個(gè)字節(jié),fgetc有可能從內(nèi)核中預(yù)讀1024個(gè)字節(jié)到I/O緩沖區(qū)中,再返回第一個(gè)字節(jié),這時(shí)該文件在內(nèi)核中記錄的讀寫位置是1024,而在FILE結(jié)構(gòu)體中記錄的讀寫位置是1。注意返回值類型是ssize_t,表示有符號(hào)的size_t,這樣既可以返回正的字節(jié)數(shù)、0(表示到達(dá)文件末尾)也可以返回負(fù)值-1(表示出錯(cuò))。read函數(shù)返回時(shí),返回值說(shuō)明了buf中前多少個(gè)字節(jié)是剛讀上來(lái)的。有些情況下,實(shí)際讀到的字節(jié)數(shù)(返回值)會(huì)小于請(qǐng)求讀的字節(jié)數(shù)count,例如:

讀常規(guī)文件時(shí),在讀到count個(gè)字節(jié)之前已到達(dá)文件末尾。例如,距文件末尾還有30個(gè)字節(jié)而請(qǐng)求讀100個(gè)字節(jié),則read返回30,下次read將返回0。

從終端設(shè)備讀,通常以行為單位,讀到換行符就返回了。

從網(wǎng)絡(luò)讀,根據(jù)不同的傳輸層協(xié)議和內(nèi)核緩存機(jī)制,返回值可能小于請(qǐng)求的字節(jié)數(shù),后面socket編程部分會(huì)詳細(xì)講解。

write函數(shù)向打開(kāi)的設(shè)備或文件中寫數(shù)據(jù)

#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); 返回值:成功返回寫入的字節(jié)數(shù),出錯(cuò)返回-1并設(shè)置errno
寫常規(guī)文件時(shí),write的返回值通常等于請(qǐng)求寫的字節(jié)數(shù)count,而向終端設(shè)備或網(wǎng)絡(luò)寫則不一定。

讀常規(guī)文件是不會(huì)阻塞的,不管讀多少字節(jié),read一定會(huì)在有限的時(shí)間內(nèi)返回。從終端設(shè)備或網(wǎng)絡(luò)讀則不一定,如果從終端輸入的數(shù)據(jù)沒(méi)有換行符,調(diào)用read讀終端設(shè)備就會(huì)阻塞,如果網(wǎng)絡(luò)上沒(méi)有接收到數(shù)據(jù)包,調(diào)用read從網(wǎng)絡(luò)讀就會(huì)阻塞,至于會(huì)阻塞多長(zhǎng)時(shí)間也是不確定的,如果一直沒(méi)有數(shù)據(jù)到達(dá)就一直阻塞在那里。同樣,寫常規(guī)文件是不會(huì)阻塞的,而向終端設(shè)備或網(wǎng)絡(luò)寫則不一定。

現(xiàn)在明確一下阻塞(Block)這個(gè)概念。當(dāng)進(jìn)程調(diào)用一個(gè)阻塞的系統(tǒng)函數(shù)時(shí),該進(jìn)程被置于睡眠(Sleep)狀態(tài),這時(shí)內(nèi)核調(diào)度其它進(jìn)程運(yùn)行,直到該進(jìn)程等待的事件發(fā)生了(比如網(wǎng)絡(luò)上接收到數(shù)據(jù)包,或者調(diào)用sleep指定的睡眠時(shí)間到了)它才有可能繼續(xù)運(yùn)行。與睡眠狀態(tài)相對(duì)的是運(yùn)行(Running)狀態(tài),在Linux內(nèi)核中,處于運(yùn)行狀態(tài)的進(jìn)程分為兩種情況:

正在被調(diào)度執(zhí)行。CPU處于該進(jìn)程的上下文環(huán)境中,程序計(jì)數(shù)器(eip)里保存著該進(jìn)程的指令地址,通用寄存器里保存著該進(jìn)程運(yùn)算過(guò)程的中間結(jié)果,正在執(zhí)行該進(jìn)程的指令,正在讀寫該進(jìn)程的地址空間。

就緒狀態(tài)。該進(jìn)程不需要等待什么事件發(fā)生,隨時(shí)都可以執(zhí)行,但CPU暫時(shí)還在執(zhí)行另一個(gè)進(jìn)程,所以該進(jìn)程在一個(gè)就緒隊(duì)列中等待被內(nèi)核調(diào)度。系統(tǒng)中可能同時(shí)有多個(gè)就緒的進(jìn)程,那么該調(diào)度誰(shuí)執(zhí)行呢?內(nèi)核的調(diào)度算法是基于優(yōu)先級(jí)和時(shí)間片的,而且會(huì)根據(jù)每個(gè)進(jìn)程的運(yùn)行情況動(dòng)態(tài)調(diào)整它的優(yōu)先級(jí)和時(shí)間片,讓每個(gè)進(jìn)程都能比較公平地得到機(jī)會(huì)執(zhí)行,同時(shí)要兼顧用戶體驗(yàn),不能讓和用戶交互的進(jìn)程響應(yīng)太慢。

下面這個(gè)小程序從終端讀數(shù)據(jù)再寫回終端。

例 28.2. 阻塞讀終端

#include <unistd.h>
#include <stdlib.h>
?int main(void)
?{
?char buf[10];
?int n;
?n = read(STDIN_FILENO, buf, 10);
?if (n < 0)
?{
?perror("read STDIN_FILENO");
?exit(1);
?}
?write(STDOUT_FILENO, buf, n);
?return 0;
?}


執(zhí)行結(jié)果如下:

$ ./a.out hello(回車) hello $ ./a.out hello world(回車) hello worl$ d bash: d: command not found
第一次執(zhí)行a.out的結(jié)果很正常,而第二次執(zhí)行的過(guò)程有點(diǎn)特殊,現(xiàn)在分析一下:

Shell進(jìn)程創(chuàng)建a.out進(jìn)程,a.out進(jìn)程開(kāi)始執(zhí)行,而Shell進(jìn)程睡眠等待a.out進(jìn)程退出。

a.out調(diào)用read時(shí)睡眠等待,直到終端設(shè)備輸入了換行符才從read返回,read只讀走10個(gè)字符,剩下的字符仍然保存在內(nèi)核的終端設(shè)備輸入緩沖區(qū)中。

a.out進(jìn)程打印并退出,這時(shí)Shell進(jìn)程恢復(fù)運(yùn)行,Shell繼續(xù)從終端讀取用戶輸入的命令,于是讀走了終端設(shè)備輸入緩沖區(qū)中剩下的字符d和換行符,把它當(dāng)成一條命令解釋執(zhí)行,結(jié)果發(fā)現(xiàn)執(zhí)行不了,沒(méi)有d這個(gè)命令。

如果在open一個(gè)設(shè)備時(shí)指定了O_NONBLOCK標(biāo)志,read/write就不會(huì)阻塞。以read為例,如果設(shè)備暫時(shí)沒(méi)有數(shù)據(jù)可讀就返回-1,同時(shí)置errno為EWOULDBLOCK(或者EAGAIN,這兩個(gè)宏定義的值相同),表示本來(lái)應(yīng)該阻塞在這里(would block,虛擬語(yǔ)氣),事實(shí)上并沒(méi)有阻塞而是直接返回錯(cuò)誤,調(diào)用者應(yīng)該試著再讀一次(again)。這種行為方式稱為輪詢(Poll),調(diào)用者只是查詢一下,而不是阻塞在這里死等,這樣可以同時(shí)監(jiān)視多個(gè)設(shè)備:

while(1) { 非阻塞read(設(shè)備1); if(設(shè)備1有數(shù)據(jù)到達(dá)) 處理數(shù)據(jù); 非阻塞read(設(shè)備2); if(設(shè)備2有數(shù)據(jù)到達(dá)) 處理數(shù)據(jù); ... }
如果read(設(shè)備1)是阻塞的,那么只要設(shè)備1沒(méi)有數(shù)據(jù)到達(dá)就會(huì)一直阻塞在設(shè)備1的read調(diào)用上,即使設(shè)備2有數(shù)據(jù)到達(dá)也不能處理,使用非阻塞I/O就可以避免設(shè)備2得不到及時(shí)處理。

非阻塞I/O有一個(gè)缺點(diǎn),如果所有設(shè)備都一直沒(méi)有數(shù)據(jù)到達(dá),調(diào)用者需要反復(fù)查詢做無(wú)用功,如果阻塞在那里,操作系統(tǒng)可以調(diào)度別的進(jìn)程執(zhí)行,就不會(huì)做無(wú)用功了。在使用非阻塞I/O時(shí),通常不會(huì)在一個(gè)while循環(huán)中一直不停地查詢(這稱為Tight Loop),而是每延遲等待一會(huì)兒來(lái)查詢一下,以免做太多無(wú)用功,在延遲等待的時(shí)候可以調(diào)度其它進(jìn)程執(zhí)行。

while(1) { 非阻塞read(設(shè)備1); if(設(shè)備1有數(shù)據(jù)到達(dá)) 處理數(shù)據(jù); 非阻塞read(設(shè)備2); if(設(shè)備2有數(shù)據(jù)到達(dá)) 處理數(shù)據(jù); ... sleep(n); }
這樣做的問(wèn)題是,設(shè)備1有數(shù)據(jù)到達(dá)時(shí)可能不能及時(shí)處理,最長(zhǎng)需延遲n秒才能處理,而且反復(fù)查詢還是做了很多無(wú)用功。以后要學(xué)習(xí)的select(2)函數(shù)可以阻塞地同時(shí)監(jiān)視多個(gè)設(shè)備,還可以設(shè)定阻塞等待的超時(shí)時(shí)間,從而圓滿地解決了這個(gè)問(wèn)題。

以下是一個(gè)非阻塞I/O的例子。目前我們學(xué)過(guò)的可能引起阻塞的設(shè)備只有終端,所以我們用終端來(lái)做這個(gè)實(shí)驗(yàn)。程序開(kāi)始執(zhí)行時(shí)在0、1、2文件描述符上自動(dòng)打開(kāi)的文件就是終端,但是沒(méi)有O_NONBLOCK標(biāo)志。所以就像例 28.2 “阻塞讀終端”一樣,讀標(biāo)準(zhǔn)輸入是阻塞的。我們可以重新打開(kāi)一遍設(shè)備文件/dev/tty(表示當(dāng)前終端),在打開(kāi)時(shí)指定O_NONBLOCK標(biāo)志。

例 28.3. 非阻塞讀終端

#include <unistd.h>
#include <fcntl.h>
?#include <errno.h>
?#include <string.h>
?#include <stdlib.h>
?#define MSG_TRY "try again\n"
?int main(void)
?{
?char buf[10];
?int fd, n;
?fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
?if(fd<0) { perror("open /dev/tty"); exit(1); }
?tryagain: n = read(fd, buf, 10); if (n < 0)
?{
?if (errno == EAGAIN)
?{
?sleep(1);
?write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
?goto tryagain;
?}
?perror("read /dev/tty");
?exit(1);
?}
?write(STDOUT_FILENO, buf, n);
?close(fd);
?return 0;
?}


以下是用非阻塞I/O實(shí)現(xiàn)等待超時(shí)的例子。既保證了超時(shí)退出的邏輯又保證了有數(shù)據(jù)到達(dá)時(shí)處理延遲較小。

例 28.4. 非阻塞讀終端和等待超時(shí)

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
?#include <stdlib.h>
?#define MSG_TRY "try again\n"
?#define MSG_TIMEOUT "timeout\n"
?int main(void)
?{
?char buf[10];
?int fd, n, i;
?fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
?if(fd<0) { perror("open /dev/tty"); exit(1); }
?for(i=0; i<5; i++)
?{
?n = read(fd, buf, 10);
?if(n>=0) break;
?if(errno!=EAGAIN) {
?perror("read /dev/tty"); exit(1);
?}
?sleep(1);
?write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
?}
?if(i==5)
?write(STDOUT_FILENO, MSG_TIMEOUT, strlen(MSG_TIMEOUT));
?else write(STDOUT_FILENO, buf, n); close(fd); return 0;
?}


?


?

總結(jié)

以上是生活随笔為你收集整理的fread函数和fwrite函数,read,write的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。