1.打開文件
函數功能: 打開一個文件
函數原型:FILE * fopen(const char * path,const char * mode);
相關函數:open,fclose,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);
輸入參數
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 "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