歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux基礎知識 >> Linux文件操作

Linux文件操作

日期:2017/3/2 17:13:56   编辑:Linux基礎知識

Linux中一切都是文件。如普通文件,目錄,設備,管道等。
操作這些文件有兩種方式,調用系統函數和使用標准I/O庫。

一、調用系統函數
1.文件描述符:數值類型,表示打開的文件標識
程序運行時,會首先打開3個文件描述符,0(標准輸入文件),1(標准輸出文件),2(標准錯誤文件)

2.系統調用常用函數
1)open函數:打開文件
原型為:

int open(const char *path,int oflags)
int open(const char *path,int oflags,mode_t mode)

path:完整的文件路徑
oflags:文件訪問模式(只讀,只寫,可讀寫)
mode:設定文件訪問權限

返回值:返回與文件關聯的文件描述符,失敗返回-1
注意這個描述符是唯一的,不與其他進程共享,文件對應的文件描述符並不是固定的。

2)write函數:寫入文件
原型為:

size_t write(int fildes,const void *buf,size_t nbytes);

將buf緩沖區的前nbyts個字節,寫入文件描述符files關聯的文件中。
返回值:實際寫入的字節數,失敗返回-1

3)read函數:讀取文件
原型為:

size_t read(int fildes,void *buf,szie_t nbytes);

讀取文件描述符fildes關聯的文件中前nbytes個字節,到buf緩沖區
返回值:實際讀取的字節數,失敗返回-1

4)close函數:關閉文件
原型為:

int close(int fildes);

返回值:成功返回0,失敗返回-1

3.調用系統函數示例
從一個文件中復制數據到另一個文件,代碼如下:
copy.c

#include<fcntl.h>
#include<stdlib.h>
int main()
{
    char c='\0';
    int in=-1,out=-1;
    in=open("myfile.txt",O_RDONLY);
    //以只寫方式創建文件,若文件不存在則新建一個文件
    //文件所有者具有讀和寫權限
    out=open("myfile2.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
    while(read(in,&c,1)==1)
        write(out,&c,1);
    close(in);
    close(out);
    return 0;
}

輸出結果:

4.標准I/O庫
在標准I/O中,使用的是文件流,對應著底層的文件描述符。
文件流是一個指向FILE結構的指針。

I/O庫的函數包含在頭文件stdio.h中。

1)fopen函數:打開文件
原型為:

FILE* fopen(const char *filename,const char *mode);

與底層open函數類似
返回值:成功返回非空指針,失敗返回NULL

2)fread函數:讀取文件
原型為:

size_t fread(void *ptr,size_t size,size_t nitems,FILE *stream);

與底層read函數類似
從stream讀取nitems個長度為size的數據到ptr指向的緩沖區
返回值:成功讀取的字節數,失敗返回-1

3)fwrite函數:寫入文件
原型為:

size_t fwrite(const void *ptr,size_t size,size_t nitems,FILE *stream);

與底層write函數類似
從ptr指向的緩存區讀取nitems個長度為size的數據,並把它們寫到stream對應的文件中。
返回值:成功寫入的字節數,失敗返回-1

4)fclose函數:關閉文件
原型為:

int fclose(FILE *stream);

返回值:成功返回0,失敗返回-1

5.標准I/O使用示例
與前例一樣,從一個文件中復制數據到另一個文件,只是使用I/O庫函數來實現,
代碼如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int c=0;
    FILE *pfin = NULL;
    FILE *pfout = NULL;
    pfin = fopen("myfile.txt","r");
    pfout = fopen("myfile2.txt","w");
    while(fread(&c,sizeof(char),1,pfin))
        fwrite(&c,sizeof(char),1,pfout);
    fclose(pfin);
    fclose(pfout);
    return 0;
}

輸出結果:

程序中的讀和寫數據可以用庫中的其他函數來代替,如fget,fputc等。

6.文件描述符和文件流
一般不要混合使用底層輸入輸出與高層文件流操作。
調用fileno函數,可以獲得文件流使用的底層文件描述符
原型為:int fileno(FILE *stream);
調用fdopen函數,可以在一個已經打開的文件描述符上創建一個新的文件流
原型為:FILE* fdopen(int fildes,const char* mode);

Linux下編程時,一般使用系統調用,而不使用I/O庫。
有些操作必須使用系統調用,如創建文件讀寫鎖等。

7.系統調用性能優化
我們使用time命令測試系統調用和I/O庫兩種方法的運行時間,
結果如下所示:

可以看出,系統調用的效率要明顯低於I/O庫,這是為什麼呢?
因為系統調用時,Linux必須從運行用戶代碼切換到內核代碼,然後再返回用戶代碼。
而I/O庫函數會自動在數據滿足數據塊長度時,才調用底層系統函數。

系統調用代碼優化如下,每次一次性讀取和寫入N個字節,減少系統調用次數。

copyopt.c

#include<fcntl.h>
#include<stdlib.h>
int main()
{
    char buffer[1024];
    int in=-1,out=-1;
    int nread=0;
    in=open("myfile.txt",O_RDONLY);
    //以只寫方式創建文件,若文件不存在則新建一個文件
    //文件所有者具有讀和寫權限
    out=open("myfile2.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
    while(nread=read(in,buffer,sizeof(buffer))>0)
        write(out,buffer,nread);
    close(in);
    close(out);
    return 0;
}

使用time測試輸出如下:

可以看出,性能得到了提高,甚至超過了使用I/O的性能。

Copyright © Linux教程網 All Rights Reserved