UNIX - 標準I/O庫

流和FILE對象

對於標準I/O庫,其操作是針對流(stream)進行的。當用標準I/O庫打開或創建一個文件時,既已使一個流與一個文件相關聯。

流的定向(stream’s orientation)
流的定向決定了所讀、寫的字符是單字節還是多字節的。當一個流最初被創建時,它未被定向。如果在一個未定向的流上使用一個單字節I/O函數,則將流的定向被設置爲字節定向的。如果在一個未定向的流上使用一個多字節I/O函數,則將流的定向被設置爲寬定向(多字節)的。

只有兩個函數能夠改變流的定向。freopen函數清除一個流的定向;fwide函數設置流的定向。

#include <wchar.h>
int fwide(FILE *stream, int mode);
返回值:若流是寬定向的則返回正值,若流是字節定向的則返回負值,若流是未定向的則返回0.

fwide函數由通過mode參數決定流的定向:

  • 若 mode > 0,將流設置爲寬定向的;
  • 若 mode < 0,將流設置爲字節定向的;
  • 若 mode = 0,不設置流的定向,但是返回標識該流定向的值。

例1. 使用fwide設置流的定向

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    int wd = 0;
    int wide = 0;

    if (argc != 3){
        printf("Usage: %s <path> <wide>\n", argv[0]);
        exit(1);
    }

    fp = fopen(argv[1], "r");
    if (!fp){
        printf("Open stream failed\n");
        exit(-1);
    }

    wide = atoi(argv[2]);
    wd = fwide(fp, wide);
    if (wd > 0)
        printf("%d : stream is wide-character oriented.\n", wd);
    else if (wd < 0)
        printf("%d : stream is byte oriented.\n", wd);
    else 
        printf("%d : stream has no orientation yet.\n", wd);

    fclose(fp);

    return 0;
}

將流設置爲字節定向的:

$ ./a.out file -3
-1 : stream is byte oriented.

將流設置爲寬定向的:

$ ./a.out file 3
1 : stream is wide-character oriented.

獲取流的定向:

$ ./a.out file 0
0 : stream has no orientation yet.

當打開一個流時,標準I/O函數fopen返回一個指向FILE對象的指針。該對象是一個結構體,它包含了標準I/O庫爲管理流所需的所有信息,包括:用於實際I/O的文件描述符、指向該流緩衝區的指針、緩衝區的長度、當前在緩衝區的字符數以及出錯標誌等。

FILE結構體定義:
[ /usr/include/libio.h ]

struct _IO_FILE {
    int _flags;     /* High-order word is _IO_MAGIC; rest is flags. */
    #define _IO_file_flags _flags
    /* The following pointers correspond to the C++ streambuf protocol. */
    /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
    char* _IO_read_ptr; /* Current read pointer */
    char* _IO_read_end; /* End of get area. */
    char* _IO_read_base;    /* Start of putback+get area. */
    char* _IO_write_base;   /* Start of put area. */
    char* _IO_write_ptr;    /* Current put pointer. */
    char* _IO_write_end;    /* End of put area. */
    char* _IO_buf_base; /* Start of reserve area. */
    char* _IO_buf_end;  /* End of reserve area. */
    /* The following fields are used to support backing up and undo. */
    char *_IO_save_base; /* Pointer to start of non-current get area. */
    char *_IO_backup_base;  /* Pointer to first valid character of backup area */
    char *_IO_save_end; /* Pointer to end of non-current get area. */

    struct _IO_marker *_markers;

    struct _IO_FILE *_chain;

    int _fileno;

    #if 0
        int _blksize;
    #else
        int _flags2;
    #endif
        _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

    #define __HAVE_COLUMN /* temporary */
    /* 1+column number of pbase(); 0 is unknown. */
    unsigned short _cur_column;
    signed char _vtable_offset;
    char _shortbuf[1];

    /*  char* _save_gptr;  char* _save_egptr; */

    _IO_lock_t *_lock;
    #ifdef _IO_USE_OLD_IO_FILE
};

[ /usr/include/stdio.h ]

__BEGIN_NAMESPACE_STD
/* The opaque type of streams.  This is the definition used elsewhere.  */
typedef struct _IO_FILE FILE;
__END_NAMESPACE_STD

標準輸入、標準輸出和標準出錯

對一個進程預定義了三個流,且這三個流能自動被進程使用,它們是標準輸入、標準輸出和標準出錯。
這三個標準I/O流通過預定義文件指針stdin、stdout和stderr加以引用。這三個指針同樣在stdio.h中定義。

/* Standard streams.  */
extern struct _IO_FILE *stdin;          /* Standard input stream. */
extern struct _IO_FILE *stdout;         /* Standard output stream. */
extern struct _IO_FILE *stderr;         /* Standard error output stream. */
/* C89/C99 say they're macros.  Make them happy.  */
#define stdin stdin
#define stdout stdout
#define stderr stderr
發佈了24 篇原創文章 · 獲贊 6 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章