fread函數和fwrite函數,read,write

fread函數和fwrite函數

?1.函數功能

? 用來讀寫一個數據塊

2.一般調用形式

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

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

3.說明

? (1)buffer:是一個指針,對fread來說,它是讀入數據的存放地址。對fwrite來說,是要輸出數據的地址

? (2)size:要讀寫的字節數

? (3)count:要進行讀寫多少個size字節的數據項;// 1代表二進制

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

?注意:

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

?????????? 2 完成一次讀操作(fread())后,如果沒有關閉流(fclose()),則指針(FILE * fp)自動向后移動前一次讀寫的長度,不關閉流繼續下一次讀操作則接著上次的輸出繼續輸出;

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

文件使用之后一定要關閉,否則將不能正確顯示內容.fwrite:讀入兩個學生信息然后用fwrite存入文件

fread:用fread從文件中讀出學生信息。

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語言中進行文件操作時,我們經常用到fread()和fwrite(),用它們來對文件進行讀寫操作。下面詳細紹一下這兩個函數的用法。

? 我們在用C語言編寫程序時,一般使用標準文件系統,即緩沖文件系統。系統在內存中為每個正在讀寫的文件開辟“文件緩沖區”,在對文件進行讀寫時數據都經過緩沖區。要對文件進行讀寫,系統首先開辟一塊內存區來保存文件信息,保存這些信息用的是一個結構體,將這個結構體typedef為FILE類型。我們首先要定義一個指向這個結構體的指針,當程序打開一個文件時,我們獲得指向FILE結構的指針,通過這個指針,我們就可以對文件進行操作。例如:

#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;

}

? 通過以上代碼,我們就在c盤的根目錄下建立了一個名為example擴展名為.txt的文件,我們打開可以看到上面寫上了This is a test。當我們對它將它讀出時,用如下代碼:

#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;

}

?可以看到,當我們使用memset了以后,讀出了一大堆亂碼,這是為什么呢?原因是我們在fwrite函數時寫入的字節數是用strlen求得的,也就是說字符串最后的'\0'并沒有寫到文件中去。所以我們從文件中讀到buffer中時也自然沒有'\0',因為buffer中的數是隨機的,除非buffer中最后一個字符的下一個數恰好隨機到0(可能性很小,這里用memset將它排除),否則以%s將buffer中的字符輸出時遇不到0,所以亂碼產生。解決的辦法有很多,你可以在向文件寫數據時多寫入一個字節,系統會自動寫入0,fwrite(buffer, 1, strlen("This is a test")+1, fp);這樣讀出時最后就有一個0了。或者讀出操作完成后,在最后一個字符后面補上一個0:buffer[len] = 0;這樣問題也可得到解決。
?
fread函數和fwrite函數 1.函數功能

? 用來讀寫一個數據塊。

2.一般調用形式

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

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

3.說明

? (1)buffer:是一個指針,對fread來說,它是讀入數據的存放地址。對fwrite來說,是要輸出數據的地址。

? (2)size:要讀寫的字節數;

? (3)count:要進行讀寫多少個size字節的數據項;

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

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

?????????? 2 完成一次讀操作(fread())后,如果沒有關閉流(fclose()),則指針(FILE * fp)自動向后移動前一次讀寫的長度,不關閉流繼續下一次讀操作則接著上次的輸出繼續輸出;

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

文件使用之后一定要關閉,否則將不能正確顯示內容.fwrite:讀入兩個學生信息然后用fwrite存入文件

fread:用fread從文件中讀出學生信息。

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語言中進行文件操作時,我們經常用到fread()和fwrite(),用它們來對文件進行讀寫操作。下面詳細紹一下這兩個函數的用法。

? 我們在用C語言編寫程序時,一般使用標準文件系統,即緩沖文件系統。系統在內存中為每個正在讀寫的文件開辟“文件緩沖區”,在對文件進行讀寫時數據都經過緩沖區。要對文件進行讀寫,系統首先開辟一塊內存區來保存文件信息,保存這些信息用的是一個結構體,將這個結構體typedef為FILE類型。我們首先要定義一個指向這個結構體的指針,當程序打開一個文件時,我們獲得指向FILE結構的指針,通過這個指針,我們就可以對文件進行操作。例如:

#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;

}

? 通過以上代碼,我們就在c盤的根目錄下建立了一個名為example擴展名為.txt的文件,我們打開可以看到上面寫上了This is a test。當我們對它將它讀出時,用如下代碼:

#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;

}

?可以看到,當我們使用memset了以后,讀出了一大堆亂碼,這是為什么呢?原因是我們在fwrite函數時寫入的字節數是用strlen求得的,也就是說字符串最后的'\0'并沒有寫到文件中去。所以我們從文件中讀到buffer中時也自然沒有'\0',因為buffer中的數是隨機的,除非buffer中最后一個字符的下一個數恰好隨機到0(可能性很小,這里用memset將它排除),否則以%s將buffer中的字符輸出時遇不到0,所以亂碼產生。解決的辦法有很多,你可以在向文件寫數據時多寫入一個字節,系統會自動寫入0,fwrite(buffer, 1, strlen("This is a test")+1, fp);這樣讀出時最后就有一個0了。或者讀出操作完成后,在最后一個字符后面補上一個0:buffer[len] = 0;這樣問題也可得到解決。
?

?
?
?
?
/***
*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| 評論????????????? 2009-7-29 20:06 zawdd | 七級
stdio.h
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
把數據寫入一個數據流
這個例子中實現了把從A到Z的26個字符寫入文件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
從一個數據流中讀取數據
使用實例:請參看feof函數
feof
stdio.h
int feof( FILE *stream );
測試文件指針是否指向數據流的尾部,若是則返回0,否則返回-1
這個例子中打開文件sample.txt,每次讀取10個字節,直到所以的字節被讀完為止:
??? 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("出錯!");
??????????? break;
??????? }
??????? Size = Size + count;
??? }
??? fclose(p);

?

?

?

?

read函數從打開的設備或文件中讀取數據。

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

返回值:成功返回讀取的字節數,出錯返回-1并設置errno如果在調read之前已到達文件末尾,則這次read返回0
?

參數count是請求讀取的字節數,讀上來的數據保存在緩沖區buf,同時文件的當前讀寫位置向后移。注意這個讀寫位置和使用C標準I/O庫時的讀寫位置有可能不同,這個讀寫位置是記在內核中的,而使用C標準I/O庫時的讀寫位置是用戶空間I/O緩沖區中的位置。比如用fgetc讀一個字節,fgetc有可能從內核中預讀1024個字節到I/O緩沖區中,再返回第一個字節,這時該文件在內核中記錄的讀寫位置是1024,而在FILE結構體中記錄的讀寫位置是1。注意返回值類型是ssize_t,表示有符號的size_t,這樣既可以返回正的字節數、0(表示到達文件末尾)也可以返回負值-1(表示出錯)。read函數返回時,返回值說明了buf中前多少個字節是剛讀上來的。有些情況下,實際讀到的字節數(返回值)會小于請求讀的字節數count,例如:

讀常規文件時,在讀到count個字節之前已到達文件末尾。例如,距文件末尾還有30個字節而請求讀100個字節,則read返回30,下次read將返回0。

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

從網絡讀,根據不同的傳輸層協議和內核緩存機制,返回值可能小于請求的字節數,后面socket編程部分會詳細講解。

write函數向打開的設備或文件中寫數據

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

讀常規文件是不會阻塞的,不管讀多少字節,read一定會在有限的時間內返回。從終端設備或網絡讀則不一定,如果從終端輸入的數據沒有換行符,調用read讀終端設備就會阻塞,如果網絡上沒有接收到數據包,調用read從網絡讀就會阻塞,至于會阻塞多長時間也是不確定的,如果一直沒有數據到達就一直阻塞在那里。同樣,寫常規文件是不會阻塞的,而向終端設備或網絡寫則不一定。

現在明確一下阻塞(Block)這個概念。當進程調用一個阻塞的系統函數時,該進程被置于睡眠(Sleep)狀態,這時內核調度其它進程運行,直到該進程等待的事件發生了(比如網絡上接收到數據包,或者調用sleep指定的睡眠時間到了)它才有可能繼續運行。與睡眠狀態相對的是運行(Running)狀態,在Linux內核中,處于運行狀態的進程分為兩種情況:

正在被調度執行。CPU處于該進程的上下文環境中,程序計數器(eip)里保存著該進程的指令地址,通用寄存器里保存著該進程運算過程的中間結果,正在執行該進程的指令,正在讀寫該進程的地址空間。

就緒狀態。該進程不需要等待什么事件發生,隨時都可以執行,但CPU暫時還在執行另一個進程,所以該進程在一個就緒隊列中等待被內核調度。系統中可能同時有多個就緒的進程,那么該調度誰執行呢?內核的調度算法是基于優先級和時間片的,而且會根據每個進程的運行情況動態調整它的優先級和時間片,讓每個進程都能比較公平地得到機會執行,同時要兼顧用戶體驗,不能讓和用戶交互的進程響應太慢。

下面這個小程序從終端讀數據再寫回終端。

例 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;
?}


執行結果如下:

$ ./a.out hello(回車) hello $ ./a.out hello world(回車) hello worl$ d bash: d: command not found
第一次執行a.out的結果很正常,而第二次執行的過程有點特殊,現在分析一下:

Shell進程創建a.out進程,a.out進程開始執行,而Shell進程睡眠等待a.out進程退出。

a.out調用read時睡眠等待,直到終端設備輸入了換行符才從read返回,read只讀走10個字符,剩下的字符仍然保存在內核的終端設備輸入緩沖區中。

a.out進程打印并退出,這時Shell進程恢復運行,Shell繼續從終端讀取用戶輸入的命令,于是讀走了終端設備輸入緩沖區中剩下的字符d和換行符,把它當成一條命令解釋執行,結果發現執行不了,沒有d這個命令。

如果在open一個設備時指定了O_NONBLOCK標志,read/write就不會阻塞。以read為例,如果設備暫時沒有數據可讀就返回-1,同時置errno為EWOULDBLOCK(或者EAGAIN,這兩個宏定義的值相同),表示本來應該阻塞在這里(would block,虛擬語氣),事實上并沒有阻塞而是直接返回錯誤,調用者應該試著再讀一次(again)。這種行為方式稱為輪詢(Poll),調用者只是查詢一下,而不是阻塞在這里死等,這樣可以同時監視多個設備:

while(1) { 非阻塞read(設備1); if(設備1有數據到達) 處理數據; 非阻塞read(設備2); if(設備2有數據到達) 處理數據; ... }
如果read(設備1)是阻塞的,那么只要設備1沒有數據到達就會一直阻塞在設備1的read調用上,即使設備2有數據到達也不能處理,使用非阻塞I/O就可以避免設備2得不到及時處理。

非阻塞I/O有一個缺點,如果所有設備都一直沒有數據到達,調用者需要反復查詢做無用功,如果阻塞在那里,操作系統可以調度別的進程執行,就不會做無用功了。在使用非阻塞I/O時,通常不會在一個while循環中一直不停地查詢(這稱為Tight Loop),而是每延遲等待一會兒來查詢一下,以免做太多無用功,在延遲等待的時候可以調度其它進程執行。

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

以下是一個非阻塞I/O的例子。目前我們學過的可能引起阻塞的設備只有終端,所以我們用終端來做這個實驗。程序開始執行時在0、1、2文件描述符上自動打開的文件就是終端,但是沒有O_NONBLOCK標志。所以就像例 28.2 “阻塞讀終端”一樣,讀標準輸入是阻塞的。我們可以重新打開一遍設備文件/dev/tty(表示當前終端),在打開時指定O_NONBLOCK標志。

例 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實現等待超時的例子。既保證了超時退出的邏輯又保證了有數據到達時處理延遲較小。

例 28.4. 非阻塞讀終端和等待超時

#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;
?}


?


?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254173.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254173.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254173.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

微信小程序 CSS filter(濾鏡)的使用示例

前言 之前在看七月老師的視頻的時候&#xff0c;看到了有一個樣式是-webkit-filter&#xff0c;不知道是什么&#xff08;我沒咋學過CSS&#xff0c;嘿嘿&#xff0c;所以不知道是啥&#xff09;&#xff0c;于是查了一下&#xff0c;原來是濾鏡吖。但是在微信小程序里使用的時…

vmware ubuntu重置root密碼

1.重啟ubuntu&#xff0c;按住shift&#xff08;開機啟動時&#xff09; 2.選擇recovery mode,enter 3.root選擇root drop to root shell prompt 4.進入shell界面設置密碼 (1)mount -rw -o remount / (2)passwd username(設置root用戶的密碼) 完成以上修改后&#xff0c;重啟就…

halcon使用直線標定板,標定相機內參代碼

read_image (Image, 直線標定板圖片/Left201118140641772.bmp) get_image_size (Image, Width, Height) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image) * Image Acquisition 01: Code generated by Image Acquisiti…

dyld: Library not loaded: @rpath/libswiftCore.dylib 解決方法

解決&#xff1a; 設置Build Setting - > 搜索 embe關鍵字 -> 修改屬性 見如下圖&#xff1a; 如果更新了Xcode 8 這里變成&#xff1a; 轉載于:https://www.cnblogs.com/yajunLi/p/5979621.html

Bootloader及u-boot簡介/u-boot系統啟動流程

Bootloader及u-boot簡介Bootloader代碼是芯片復位后進入操作系統之前執行的一段代碼&#xff0c;主要用于完成由硬件啟動到操作系統啟動的過渡&#xff0c;從而為操作系統提供基本的運行環境&#xff0c;如初始化CPU、堆棧、存儲器系統等。Bootloader 代碼與CPU 芯片的內核結構…

Dubbo之RPC架構

為什么會有dubbo的出現: 隨著互聯網的發展&#xff0c;網站應用的規模不斷擴大&#xff0c;常規的垂直應用架構已無法應對&#xff0c;分布式服務架構以及流動計算架構勢在必行&#xff0c;亟需一個治理系統確保架構有條不紊的演進。 單一應用架構 當網站流量很小時&#xff0c…

區域路由的注冊機制

AreaRegistration.RegisterAllAreas() 我們新建一個名稱為Admin的Area&#xff0c;VS生成下面的代碼。 { action , id 我們先來看AreaRegistration這個抽象類&#xff0c;實際上&#xff0c;它只有一個核心功能&#xff0c;就是RegisterAllAreas&#xff0c;獲取所有繼承它的…

Unix/Linux IPC及線程間通信總結

一、互斥與同步 1.互斥&#xff1a;是指某一資源同時只允許一個訪問者對其進行訪問&#xff0c;具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序&#xff0c;即訪問是無序的。 2.同步&#xff1a;是指在互斥的基礎上&#xff08;大多數情況&#xff09;&#xff0…

CSS樣式的插入方式

1.外部樣式&#xff1a; 當樣式需要應用于很多頁面時&#xff0c;外部樣式表將是理想的選擇。<head><link rel"stylesheet" type"text/css" href"mystyle.css" /> </head> 2.內部樣式 當單個文檔需要特殊的樣式時&#…

嵌入式Linux系統基礎知識

一、嵌入式Linux系統的構成 1、硬件 2、內核 3、應用程序&#xff08;形成根文件系統&#xff09; 二、構建嵌入式Linux系統的主要任務 1、內核部分 2、應用程序部分 嵌入式Linux的開發大致可分為三個層次&#xff1a;引導裝載內核、構造文件系統和圖形用戶界面。作為操作系統…

win10系統javac不是內部或外部命令,也不是可運行的程序 或批處理文件。

按照下面的步驟設置環境變量 說明&#xff1a; 1. 如果編輯的是系統環境變量&#xff0c;命令提示符需要以管理員權限運行&#xff1b;如果在用戶環境變量中編輯&#xff0c;則當前用可直接運行命令提示符。 2. win10中的路徑相對于win7要設置成絕對路徑。 1&#xff0e;打開…

兩個bat文件

1、修改后綴名 ren *.cs *.txt ren *.txt *.zip2、修改文件名稱 echo offset a00setlocal EnableDelayedExpansionfor %%n in (*.txt) do (set /A a1ren "%%n" "!a!.txt")

各種排序筆記---基于比較排序部分

1. 選擇排序 selection sort 大循環 從左到右每次以一個點開始掃描array 小循環 找到從當前起始點開始的最小值 時間復雜度為O(N^2) //selection sort an array array[] public class Solution {public int[] solve(int[] array) {if (array null || array.length 0) {return…

是什么讓深度學習再次崛起并超越人類?

作者潘爭&#xff0c;格靈深瞳計算機視覺工程師&#xff0c;清華大學自動化系博士&#xff0c;師從智能技術與系統國家重點實驗室副主任張長水。深度學習(Deep Learning)這個詞最近借著AlphaGO與李世石的人機大戰又火了一把。深度學習其實是機器學習(Machine Learning)的一個分…

常見的流量問題

常見的流量問題 冗余內容同類請求被間隔執行&#xff0c;請求的內容包含一些相對靜態的信息&#xff0c;正確的處理是第一次請求包括靜態信息就好&#xff0c;后面的同類請求只包含必要的即時變化信息即可。錯誤的處理方式是每次請求服務器都返回一次靜態信息。 冗余請求有的時…

halcon使用點擬合圓形時候,點集順序紊亂,不影響圓形擬合效果

read_image (Image, 截圖20201226094342972.bmp) * Matching 01: BEGIN of generated code for model initialization set_system (border_shape_models, false) * Matching 01: Obtain the model image * Matching 01: The image is assumed to be made available in the * Ma…

Socket理解。

其他大部分系統&#xff0c;例如CRM/CMS/權限框架/MIS之類的&#xff0c;無論怎么復雜&#xff0c;基本上都能夠本地代碼本地調試&#xff0c;性能也不太重要。&#xff08;也許這個就是.net的企業級開發的戰略吧&#xff09; 可是來到通訊系統&#xff0c;一切變得困難復雜。原…

多元化時代敏捷軟件開發的崛起與傳統軟件工程的延續

多元化時代敏捷軟件開發的崛起與傳統軟件工程的延續 1.傳統軟件開發模式 1.1瀑布模型 1.1.1概念 瀑布模型&#xff0c;顧名思義&#xff0c;軟件開發的過程如同瀑布飛流一般&#xff0c;自上而下&#xff0c;逐級下落。瀑布模型的核心思想是將問題按照工序進行簡化&#xff0c;…

Linux中的cron計劃任務配置詳解

cron來源于希臘單詞chronos&#xff08;意為“時間”&#xff09;&#xff0c;指Linux系統下一個自動執行指定任務的程序&#xff08;計劃任務&#xff09; ####1. crontab命令選項代碼如下: #crontab -u <-l, -r, -e> -u指定一個用戶 -l列出某個用戶的任務計劃 -r刪除某…

new和delete

和 sizeof 類似&#xff0c;sizeof不是函數&#xff0c;它是一個操作符&#xff0c;它在編譯期就完成了計算&#xff0c;在函數運行期間它已經是一個常數值了。 int a;sizeof(int) 4;sizeof(a) 4;sizeof a ——也是4 不需要括號&#xff01;此時要注意&#xff1a;sizeof in…