GNU/Linux应用程序开发学习笔记(一) 文件操作
时间:2011-02-05 来源:Endlessor
GNU/Linux的文件操作是通过标准C库实现的,可以用同一个API创建ASCII或二进制文件,其中文件操作函数有很多个,分别对应不同方面的功能,可谓是面面具到,下面就逐一学习。
1.Header file
在C中 ,
#include <stdio.h>
在C++中,
#include <cstdio>
2.Open File
一般用fopen()函数来打开文件,fclose()函数关闭文件。
FILE* fopen(const char* filename, const char* mode);
其中mode是文件访问模式:
* r 打开一个已经存在的文件进行度操作
* w 打开一个文件进行写操作
* a 对文件进行追加操作
* rw 对文件进行读写操作
上面后三个模式中,如果文件不存在,则会创建一个新文件filename,而第一个返回 (FILE*)NULL.
文件字符接口
对文件进行逐个字符操作时,可使用如下两个函数:
int fputc(int c, FILE* stream); int fgetc(FILE* stream);
其中fputc()中是int类型,别忘了类型转换,示例:
int func() { char str[] = "Hey, it's just a test!"; FILE* fin = fopen(filename,"a"); FILE* fout = fopen(filename,"r"); if(fout == (FILE*)NULL || fin == (FILE*)NULL) exit(-1); int i = 0; // write string STR to the file every bytes while(str[i] != NULL) { fputc((int)str[i],fin); ++i; } // get bytes from file through fgetc() until the end of the file while( (ch=fgetc(fout)) != EOF ) { printf("%c",ch); } fclose(fin); fclose(fout); return 0; }
字符串接口
对文件进行逐字符串的操作函数和字符操作函数类似,用法也类似
fputs() , fgets();
ASCII字符文件操作
这类文件操作也是比较常见的操作,应用很广,主要以下几种:
int fprintf(FILE* stream, const char* format, ...); int fscanf(FILE* stream, const char* format, ...); int sprintf(char* str, const char* format, ...); int sscanf(char* str, const char* format, ...);
二进制文件的读写
这类文件操作比较重要,特点是处理快,适用范围广,先看fread和fwrite
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); size_t fwrite(const void* ptr, size_t size, size_t nmemb,FILE* stream);
其中ptr指的是所需要处理的对象组,比如字符串或者结构题数组,size代表每个对象的字节数,nmemb代表对象的数目,这里要注意:当对象组是字符串时,nmemb=str_len+1,原因是字符串最后的'\0'不能省略。
void rewind(FILE* stream);
重置文件流指针到文件首。
int fseek(FILE* stream, long offset, int whence);
这个函数是设置文件流指针,offset是偏移值,whence有几个标志:
* SEEK_SET 将指针移到距离文件首offset个字节的位置
* SEEK_CUR 将指针移到距离当前指针位置后offset个字节的位置
* SEEK_END 将指针移到距离文件尾offset个字节的位置
注意:offset为正数时表示指针向后移动,为负数时向前移动,这个地方写了程序各种测试才发现,以前以为SEEK_END是将指针向前移动offset字节....无语......
long ftell(FILE* stream);
此函数返回文件流的指针位置,是long型,通过这个可以方便的查看文件指针的位置。
还有两个和上面功能一样的函数是fgetpos,fsetpos,但是使用目的也不一样,ftell和fseek函数没有对其机制的细节进行抽象,所以推荐使用fgetpos,fsetpos,原型如下:
int fgetpos(FILE* stream, fpos_t* pos); int fsetpos(FILE* stream, fpos_t* pos);
这两个函数通过对指针位置的抽象操作和细节描述达到比ftell,fseek更加直观的目的,他们返回的不是指针的绝对位置,而是抽象位置,所以就可以用fpos_t类型来对文件位置进行描述。
上面这些是对二进制文件操作的函数,下面是示例:
#include <iostream> #include <cstdio> using namespace std; #define MAXN_STR 40 #define MAXN_OBJECT 3 char file_name[] = "input"; char str[] = "This is a test."; FILE* fout; FILE* fin; typedef struct{ int id; float x; float y; char str[MAXN_STR+1]; }TYPE_NODE; TYPE_NODE object[MAXN_OBJECT]={ {1,10.2,12.2,"The earth"}, {2,20.9,20.8,"The arm"}, {3,12.3,12.4,"The null"} }; TYPE_NODE tmp_object; int main() { fin = fopen(file_name,"w"); if(fin == (FILE*)NULL) { exit(-1); } fwrite((void*)object,sizeof(TYPE_NODE),MAXN_OBJECT,fin); fwrite((void*)str,sizeof(str[0]),strlen(str)+1,fin); fclose(fin); fout = fopen(file_name,"r"); if(fout == (FILE*)NULL) { exit(-1); } char ss[MAXN_STR]; int pos; for(int i = 0; i < MAXN_OBJECT; ++i) { rewind(fout); fseek(fout,(i*sizeof(TYPE_NODE)),SEEK_CUR); pos = ftell(fout); printf("cur pos %d\n",pos); fread(&tmp_object,sizeof(TYPE_NODE),1,fout); printf("%d %f %f %s\n",tmp_object.id,tmp_object.x, tmp_object.y,tmp_object.str); } fread(ss,sizeof(ss[0]),strlen(str)+1,fout); printf("%s\n",ss); fclose(fout); return 0; }
基础API
这里之写出两个:
ssize_t pread(int filedes, void* buf, size_t nbyte, off_t offset); ssize_t pwrite(int filedes, void* buf, size_t nbyte, off_t offset);
这两个函数需要设置offset来对文件进行读写,但是不会影响文件指针,比较适合随机查找的情况。
====== 总结之 文件操作API======
FILE* fopen(const char* filename,const char* mode); FILE* fdopen(int filedes, const char* type); int fputc(int c,FILE* stream); int fgetc(FILE* stream); int fprintf(FILE* stream, const char* format, ...); int fscanf(FILE* stream, const char* format, ...); int sprintf(char* str, const char* format, ...); int sscanf(char* str, const char* format, ...); size_t fread(void* ptr,size_t size,size_t nmemb,FILE* stream); size_t fwrite(const void* ptr,size_t size,size_t nmemb,FILE* stream); void rewind(FILE* stream); long ftell(FILE* stream); int fseek(FILE* stream,long offset, int whence); int lseek(FILE* stream,long offset, int whence); int fgetpos(FILE* stream, fpos_t* pos); int fsetpos(FILE* stream, fpos_t* pos); int fclose(FILE* stream); int open(const char* pathname, int flags); int open(const char* pathname, int flags, mode_t mode);