Linux系統中提供了系統調用函數open()和close()用於打開和關閉一個存在的文件
int open(const char *pathname,int flags)
int open(const char *pathname,int flags,mode_t mode)
int open(const char *pathname,mode_t mode)
其中flag代表文件的打開方式
O_RDONLY: 以只讀方式打開文件
O_WRONLY:以只寫的方式打開文件
O_RDWR:以讀寫的方式打開文件
O_CREAT:若打開的文件不存在,則創建該文件
O_EXCL:如果打開文件是設置了O_CREAT,但是該文件存在,則導致調用失敗
O_TRUNC:如果以只寫或只讀方式打開一個已存在的文件,將該文件截至0
O_APPEND:追加的方式打開文件
O_NONBLOCK:用於非堵塞接口i/o
O_NODELAY
O_SYNC:當數據被寫入外存或者其他設備后,操作才返回。
其中mode是打開的權限
S_IRWXU 00700 設置文件所有者的讀,寫,執行權限
S_IRWXG 00070 設置文件所在用戶組的讀,寫,執行權限
S_IRWXO 00007 設置其他用戶的讀,寫,執行權限
S_IRUSR 00400 設置文件所有者的讀權限
S_IWUSR 00200 設置文件所有的寫權限
S_IXUSR 00100 設置文件所有者的執行權限
S_IRGRP 00040 設置用戶組的讀權限
S_IWGRP 00020 設置用戶組的寫權限
S_IXGRP 00010 設置用戶組的執行權限
S_IROTH 00004 設置其他用戶的讀權限
S_IWOTH 00002 設置其他用戶的寫權限
S_IXOTH 00001 設置其他用戶的執行權限
文件的讀操作:
ssize_t read(int fd,void *buf,size_t count);
fd代表文件描述符,buf代表讀取的數據存放的buf指針所指向的緩沖區,count代表讀取數據的字節數
函數調用成功,返回為讀取的字節數,否則返回-1
文件讀和寫的例子
void open_and_read_file()
{
int fd,n;
char buf[100];
char *path="/home/zhf/zhf/c_prj/c_test.txt";
fd=open(path,O_RDWR);
n=read(fd,buf,20);
printf("the content is %s\n",buf);
}
在這里文件都是從頭開始讀的,那么如果我想從某個位置比如第N個字節開始讀取的時候該如何操作呢,這里就需要用到文件定位函數lseek
off_t lseek(int fildes,off_t offset,int whence);\
fildes是文件描述符
offset是偏移量
whence代表用於偏移時的相對位置,可以取如下的幾個值
SEEK_SET: 從文件的開頭位置計算偏移量
SEEK_CUR: 從當前的位置開始計算偏移量
SEEK_END: 從文件的結尾開始計算偏移量
函數修改如下: 首先采用lseek函數將文件定位到從第11個字節開始,然后read將從第11個字節開始讀取。
對於寫操作也是一樣的。
void open_and_read_file()
{
int fd,n;
char buf[100];
char *path="/home/zhf/zhf/c_prj/c_test.txt";
int i;
fd=open(path,O_RDWR);
i=lseek(fd,11,SEEK_SET);
n=read(fd,buf,20);
printf("the content is %s\n",buf);
close(fd);
}
一個完整的創建,讀,寫文件的例子:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
void write_file(int fd){
char buf[]="abcde\n";
write(fd,buf,sizeof(buf));
close(fd);
}
void read_file(){
int fd;
char *path="/home/zhf/test1.txt";
char result[20];
fd=open(path,O_RDONLY);
read(fd,result,10);
printf("The content is %s",result);
close(fd);
}
int create_file(){
int fd;
char *path="/home/zhf/test1.txt";
fd=creat(path,00777);
return fd;
}
前面介紹的操作都是基於文件描述符的文件操作,下面來介紹基於流的文件操作。兩者有什么區別呢:
緩沖文件系統的特點是:在內存開辟一個“緩沖區”,為程序中的每一個文件使用,當執行讀文件的操作時,從磁盤文件將數據先讀入內存“緩沖區”, 裝滿后再從內存“緩沖區”依此讀入接收的變量。執行寫文件的操作時,先將數據寫入內存“緩沖區”,待內存“緩沖區”裝滿后再寫入文件。由此可以看出,內存 “緩沖區”的大小,影響着實際操作外存的次數,內存“緩沖區”越大,則操作外存的次數就少,執行速度就快、效率高。一般來說,文件“緩沖區”的大小隨機器 而定。主要有fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等
2.非緩沖文件系統
緩沖文件系統是借助文件結構體指針來對文件進行管理,通過文件指針來對文件進行訪問,既可以讀寫字符、字符串、格式化數據,也可以讀寫二進制數 據。非緩沖文件系統依賴於操作系統,通過操作系統的功能對文件進行讀寫,是系統級的輸入輸出,它不設文件結構體指針,只能讀寫二進制文件,但效率高、速度 快,由於ANSI標准不再包括非緩沖文件系統,因此建議大家最好不要選擇它。本書只作簡單介紹。open, close, read, write, getc, getchar, putc, putchar 等。
open 是系統調用 返回的是文件句柄,文件的句柄是文件在文件描述副表里的索引,fopen是C的庫函數,返回的是一個指向文件結構的指針。
linux中的系統函數是open,fopen是其封裝函數。fopen可以移植,open不能
來看fopen函數:FILE *fopen(const char *path,const char *mode)
path代表文件名路徑
mode代表文件的打開方式。有 r,r+,w,w+,a,a+等方式
fgetc()函數:從文件讀取1個字節 int fgetc(FILE *stream). 如果出錯或者讀到文件末尾,則返回EOF
fputc()函數:向指定的文件寫入1個文件 int fputc(int c,FILE *stream);
實例代碼:
void fopen_file()
{
int i;
char ch;
FILE *fp;
char *path="/home/zhf/zhf/c_prj/c_test.txt";
fp=fopen(path,"r");
for(i=0;i<5;i++)
{
if ((ch=fgetc(fp)) != EOF)
{
printf("%c",ch);
}
}
}
fputc和fgetc函數只能一次性的讀取或者寫入一個字節,如果想讀取或者寫入一個字符串則需要用到fgets()和fputs()函數。
Char *fgets(char *s,int size, FILE *stream);
讀取到’\n’轉移字符為結束,並在該行末尾添加一個’\0’組成完成的字符串。在size字節范圍內沒有讀到’\n’結束符,則添加一個’\0’
int fputs(const char *s, FILE *stream);
void fopen_file()
{
int i;
char ch;
char *str;
FILE *fp;
char *path="/home/zhf/zhf/c_prj/c_test.txt";
char result[100];
fp=fopen(path,"r");
str=fgets(result,20,fp);
printf("%s\n",str);
fclose(fp);
}
同樣的基於流操作的也有文件的定位操作函數分別是fseek函數和rewind函數
int fseek(FILE *stream,long offset,int whence)
這里offset表示移動的字節數,要求位移量是long型數據。以便在文件長度大於64Kb不會出錯
whence和前面介紹的一樣。
rewind函數的作用是使位置指針重新返回文件的開頭,函數沒有返回值。