打開和關閉文件以及讀取和回退字符的操作

1.打開文件

  函數功能: 打開一個文件

  函數原型:FILE * fopen(const char * path,const char * mode);

  相關函數:openfclose,fopen_s[1] ,_wfopen

        fopen_s:窄字符

        errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );

        _wfopen:寬字符

        errno_t _wfopen_s( FILE** pFile, const wchar_t *filename, const wchar_t *mode );

  所需庫: <stdio.h>

  返回值: 文件順利打開後,指向該流的文件指針就會被返回。若果文件打開失敗則返回NULL,並把錯誤代碼存在errno 中。

  一般而言,打開文件後會作一些文件讀取或寫入的動作,若打開文件失敗,接下來的讀寫動作也無法順利進行,所以在fopen()後請作錯誤判斷及處理。

        返回值說明如下:

       

Constant System error message Value

EPERM

Operation not permitted

1

ENOENT

No such file or directory

2

ESRCH

No such process

3

EINTR

Interrupted function

4

EIO

I/O error

5

ENXIO

No such device or address

6

E2BIG

Argument list too long

7

ENOEXEC

Exec format error

8

EBADF

Bad file number

9

ECHILD

No spawned processes

10

EAGAIN

No more processes or not enough memory or maximum nesting level reached

11

ENOMEM

Not enough memory

12

EACCES

Permission denied

13

EFAULT

Bad address

14

EBUSY

Device or resource busy

16

EEXIST

File exists

17

EXDEV

Cross-device link

18

ENODEV

No such device

19

ENOTDIR

Not a directory

20

EISDIR

Is a directory

21

EINVAL

Invalid argument

22

ENFILE

Too many files open in system

23

EMFILE

Too many open files

24

ENOTTY

Inappropriate I/O control operation

25

EFBIG

File too large

27

ENOSPC

No space left on device

28

ESPIPE

Invalid seek

29

EROFS

Read-only file system

30

EMLINK

Too many links

31

EPIPE

Broken pipe

32

EDOM

Math argument

33

ERANGE

Result too large

34

EDEADLK

Resource deadlock would occur

36

EDEADLOCK

Same as EDEADLK for compatibility with older Microsoft C versions

36

ENAMETOOLONG

Filename too long

38

ENOLCK

No locks available

39

ENOSYS

Function not supported

40

ENOTEMPTY

Directory not empty

41

EILSEQ

Illegal byte sequence

42

STRUNCATE

String was truncated

80


  參數說明:

  參數path字符串包含欲打開的文件路徑及文件名,參數mode字符串則代表着流形態。

  mode有下列幾種形態字符串:

  r 打開只讀文件,該文件必須存在。

  r+ 打開可讀寫的文件,該文件必須存在。

  rb+ 讀寫打開一個二進制文件,只允許讀寫數據。

  rt+ 讀寫打開一個文本文件,允許讀和寫。

  w 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則建立該文件。

  w+ 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則建立該文件。

  a 以附加的方式打開只寫文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。(EOF符保留)

  a+ 以附加方式打開可讀寫的文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。 (原來的EOF符不保留)

  wb 只寫打開或新建一個二進制文件;只允許寫數據。

  wb+ 讀寫打開或建立一個二進制文件,允許讀和寫。

  wt+ 讀寫打開或着建立一個文本文件;允許讀寫。

  at+ 讀寫打開一個文本文件,允許讀或在文本末追加數據。

  ab+ 讀寫打開一個二進制文件,允許讀或在文件末追加數據。

  上述的形態字符串都可以再加一個b字符,如rb、w+b或ab+等組合,加入b 字符用來告訴函數庫打開的文件爲二進制文件,而非純文字文件。不過在POSIX系統,包含Linux都會忽略該字符。由fopen()所建立的新文件會具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)權限,此文件權限也會參考umask 值。

  有些C編譯系統可能不完全提供所有這些功能,有的C版本不用"r+","w+","a+",而用"rw","wr","ar"等,讀者注意所用系統的規定。

        例:

        FILE* file = NULL;
        if(0 == fopen_s(&file, fileName, "rb+" ))

2.關閉文件

        if(NULL != file)

        {

              fclose(file);

              file = NULL;

        }

3.讀取和回退字符:

getc(FILE *stream);

int ungetc(int c, FILE *stream);
輸入參數
c 要寫入的字符,stream 文件流指針
輸出參數
字符c - 操作成功,EOF - 操作失敗(int)

Stream.h

#pragma once

class Stream
{
public:
    ~Stream(void);
    INT32 s_getc();
    BOOL s_ungetc(INT32 c);
    INT32 s_read(UINT8 * buf, INT32 len);
    INT32 s_write(UINT8 * buf, INT32 len);
    static Stream* createStreamInstance(const char* fileName);

private:
    Stream(FILE* file);
    INT32 trytoReadFromBuffer(unsigned char* buf, INT32 len);
    FILE* fp;
    unsigned char fRevertBuf[128];
    int fRevertNum;
};

Stream.cpp

#include "stdafx.h"
#include "Stream.h"
#include <assert.h>

Stream::Stream(FILE* file)
    :fp(NULL), fRevertNum(0)
{
    fp = file;
}

Stream::~Stream(void)
{
    if(fp != NULL)
    {    
        fclose(fp);
        fp = NULL;
    }
//    MessageBoxW(NULL, _T("free file."), _T("File Free"), 0);
}

INT32 Stream::trytoReadFromBuffer(unsigned char* buf, INT32 len)
{
    if(fRevertNum < 1)
        return 0;

    unsigned char* pStackTop = &fRevertBuf[fRevertNum-1];
    unsigned char* pStack = pStackTop;
    while(len-- > 0 && fRevertNum-- > 0 ) {
        *buf++ = *pStackTop--;
    }
    
    return ( pStack  - pStackTop);
}

INT32 Stream::s_getc()
{
    INT32 c = EOF;
    unsigned char ch = 0;
    if( trytoReadFromBuffer(&ch, 1) >= 1) {
        c = (INT32)ch;
    } else {
        if(fp != NULL) {
            c = getc(fp);
            if(c == EOF)
            {    
                fclose(fp);
                fp = NULL;
            }
        }
    }

    return c;
}

BOOL Stream::s_ungetc(INT32 c)
{
    
    if(c != EOF) {
        fRevertBuf[fRevertNum++] = c;
    }

    return TRUE;
}

INT32 Stream::s_read(UINT8 * buf, INT32 len)
{
    INT32 readNum = trytoReadFromBuffer(buf, len);
    if(readNum< len) {
        if(NULL != fp) {
            INT32 tobeRead = len-readNum;
            INT32 readNum1 = fread(buf+readNum, 1, tobeRead, fp);
            if(readNum1 < tobeRead)
            {    
                fclose(fp);
                fp = NULL;
            }
            readNum += readNum1;
        }
    }

    return readNum;
}

INT32 Stream::s_write(UINT8 * buf, INT32 len)
{
    assert(false);
    int writeNum = 0;
    if(NULL != fp) {
        writeNum = fwrite(buf, 1, len, fp);
        if(writeNum != len)
        {    
            fclose(fp);
            fp = NULL;
        }
    }
    return writeNum;
}

Stream* Stream::createStreamInstance(const char* fileName)
{
    FILE* file = NULL;
    if(0 == fopen_s(&file, fileName, "rb+" ))
        return new Stream(file);
    return NULL;

}


參考:

http://www.cnblogs.com/whiteyun/archive/2009/08/08/1541822.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章