1. 程式人生 > >C——檔案I/O

C——檔案I/O

C筆記——檔案I/O

庫函式
1,字串讀寫字元
fgets():原型char *fgets(char *s,int n,FILE stream),從stream流中讀取1-n的字串,遇EOF或換行符結束
fputs():原型int fputs(char *s,FILE *stream)檔案流

fopen():開啟檔案 fclose():關閉檔案

2,資料塊讀取函式
fread(buffer,size,count,fp) 讀資料塊如結構體或陣列,buffer指讀取檔案的首地址,size為其大小,count是讀取次數,fp地址指標
fwriter(buffer,size,count,fp) 寫入檔案塊

#include <stdio.h> //printf在該標頭檔案中宣告
#include <unistd.h> //STDOUT_FILENO, stdout等在該標頭檔案中宣告
#include <string.h> //strlen在該標頭檔案中宣告,具體參考man strlen
#define MSG_STR “Hello World\n”
int main(int main, char *argv[])
{
printf("%s", MSG_STR);
fputs(MSG_STR, stdout);//stdout指標準輸出流
write(STDOUT_FILENO, MSG_STR, strlen(MSG_STR));//STDOUT_FILENO檔案描述符。0標準輸入,1標準輸出,2標準出錯
return 0;
}
結果:
Hello World
Hello World
Hello World

系統呼叫
3,open() close() create() writer() read()函式詳解

(1)create()系統呼叫
int creat(const char *path, mode_t mode);
此函式用來建立一個新檔案並返回其fd。它等價於 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

eg:
int fd;
fd=creat(“text.txt”, 0644);

(2)open()系統呼叫
int open(const char *path,int oflag,/mode_t mode/):用來開啟檔案,並返回檔案描述符

(3)int close(int fd):用來關閉檔案並返回檔案描述符

(4) ssize_t write(int fd,const void *buf,size_t nbytes) 向fd 指向的檔案寫入buf指向的資料,大小不超過nbytes

(5)ssize_t read(int fd,void *buf,size_t nbytes)從fd指向的檔案中提取buf中是資料,大小不超過nbytes

#include <unistd.h>

int close(int fd); 返回值:成功返回0,出錯返回-1並設定errno
int open(const char *pathname,int oflag,mode);/*oflag指讀取檔案的狀態,O_RDONLY只讀 ,O_WRONLY 只寫,O_RDWR讀寫,此三必須要有一個; 開啟/建立檔案時,至少得使用上述三個常量中的一個;mode只有在O_CREAT時有用。
以下常量是選用的:
O_APPEND 每次寫操作都寫入檔案的末尾
O_CREAT 如果指定檔案不存在,則建立這個檔案,
mode的值 eg:664 6(user的許可權:4+2:寫執行)6(group的許可權:4+2)4(leader)
【read4(讀)write2(寫) x1(執行)】
O_EXCL 與O_CREAT一起使用,open呼叫是一個原子操作。如果要建立的檔案已存在,則返回 -1,並且修改 errno 的值
O_TRUNC 如果檔案存在,並且以只寫/讀寫方式開啟,則清空檔案全部內容
O_NOCTTY 如果路徑名指向終端裝置,不要把這個裝置用作控制終端。
O_NONBLOCK 如果路徑名指向 FIFO/塊檔案/字元檔案,則把檔案的開啟和後繼 I/O
設定為非阻塞模式(nonblocking mode)
O_NDELAY 同O_NONBLOCK。

以下三個常量同樣是選用的,它們用於同步輸入輸出

O_DSYNC 等待物理 I/O 結束後再 write。在不影響讀取新寫入的資料的前提下,不等待檔案屬性更新。
O_RSYNC read 等待所有寫入同一區域的寫操作完成後再進行
O_SYNC 等待物理 I/O 結束後再 write,包括更新檔案屬性的 I/O

**open 返回的檔案描述符一定是最小的未被使用的描述符。
返回值:若所有欲核查的許可權都通過了檢查則返回 0 值,表示成功,只要有 一個許可權被禁止則返回-1。

錯誤程式碼:
  EEXIST 引數 pathname 所指的檔案已存在,卻使用了 O_CREAT和 O_EXCL 旗標
  EACCESS 引數 pathname 所指的檔案不符合所要求測試的許可權。
  EROFS 欲測試寫入許可權的檔案存在於只讀檔案系統內。
  EFAULT 引數 pathname 指標超出可存取記憶體空間。
  EINVAL 引數 mode 不正確。
  ENAMETOOLONG 引數 pathname 太長。
  ENOTDIR 引數 pathname 不是目錄。
  ENOMEM 核心記憶體不足。
  ELOOP 引數 pathname 有過多符號連線問題。
  EIO I/O 存取錯誤。

1 #include <stdio.h>//使用printf()和perror()的
2 #include <errno.h>//引數errno
3 #include <string.h>//函式strerror()
4 #include <sys/types.h>//使用open()會使用的三個標頭檔案
5 #include <sys/stat.h>
6 #include <fcntl.h>
7
8 #define BUFSIZE 1024
9 #define MSG_STR “Hello World\n”
10
11 int main(int argc, char *argv[])
12 {
13 int fd = -1;
14 int rv = -1;
15 char buf[BUFSIZE];
16
17 fd=open(“test.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666);//O_RDWR讀寫 ,O_CREAT建立檔案 ,O_TRUNC若檔案存在且為只讀或讀寫檔案,則置為0
18 if(fd < 0)
19 {
20 perror(“Open/Create file test.txt failure”);//perror函式可以列印系統出錯的原因,引數只能是一個字串提示
21 return 0;
22 }
23 printf(“Open file returned file descriptor [%d]\n”, fd);//列印檔案描述符,判斷檔案是否執行異(常使用檔案printf來除錯檔案)
24
25 if( (rv=write(fd, MSG_STR, strlen(MSG_STR))) < 0 )//將MSG_STR即Hello World寫入檔案 strlen()函式用來計算字串的長度 標頭檔案:#include <string.h>
27 printf(“Write %d bytes into file failure: %s\n”, rv, strerror(errno));// strerror()用來依引數errno的錯誤程式碼來查詢其錯誤原因的描述
28 goto cleanup;// goto 語句標號;執行goto語句後,程式將跳轉到 語句標號: 處並執行其後的語句。
29 }
30
31 //memset(buf, 0, sizeof(buf));//void *memset(void *s,int c,size_t n),將已開闢記憶體空間 s 的首 n 個位元組的值設為值 c
32 if( (rv=read(fd, buf, sizeof(buf))) < 0 )
33 {
34 printf(“Read data from file failure: %s\n”, strerror(errno));
35 goto cleanup;
36 }
37
38 printf(“Read %d bytes data from file: %s\n”, rv, buf);
39
40 cleanup:
41 close(fd);
42
return 0;//在其他任何函式呼叫return只會讓本函式返回,而在main函式中會讓main函式退出,因其實際呼叫了exit()函式

4.perror()和strerror()返回出錯值
void perror(const char *s ):s為一段字串,勿加入換行符,將輸出到標準輸出
char *strerror(int errno):將出錯原因換成字串,較常用

eg:
#include <stdio.h> //printf()和perror()在該標頭檔案中宣告
#include <errno.h> //errno系統全域性變數在該標頭檔案中宣告
#include <string.h> //strerror()在該標頭檔案中宣告
#include <sys/types.h> //open()系統呼叫需要的三個標頭檔案
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
char *file_name = “/test.txt”; //根目錄下並不存在該檔案,在open()開啟時會失敗
int fd=-1;

fd=open(file_name, O_RDONLY, 066);
if( fd < 0 )
{
perror(“Open file failure”);
printf(“Open file %s failure: %s\n”, file_name, strerror(errno));
return 0;
}
close(fd);
}

結果:Open file failure:No Such File
Open file/test.txt failure:No Such File

5.dup()和dup2()系統呼叫

int dup(int fd):返回的檔案描述符一定是當前最小的
int dup2(int fd,int fd2):將一個新的檔案描述符指向給fd,常用於標準輸入輸出和重定向

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>//使用dup()所需標頭檔案
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv)
{
int fd = -1;
fd = open(“std.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fd < 0)
{
printf(“Open file failure: %s\n”, strerror(errno));
return ;
}

dup2(fd, STDIN_FILENO); //標準輸入重定向到 std.txt 檔案中去
dup2(fd, STDOUT_FILENO); //標準輸出重定向到 std.txt 檔案中去
dup2(fd, STDERR_FILENO); //標準出錯重定向到 std.txt 檔案中去
printf(“fd=%d\n”, fd);

close(fd);
}

6.stat()和fsta():用來返回檔案或目錄相關的資訊
int stat(const char*path,struct stat *buf)
int fstat(int fd,struct stat *buf)

struct stat {
dev_t st_dev; /* ID of device containing file /
ino_t st_ino; /
inode number /
mode_t st_mode; /
protection /
nlink_t st_nlink; /
number of hard links /
uid_t st_uid; /
user ID of owner /
gid_t st_gid; /
group ID of owner /
dev_t st_rdev; /
device ID (if special file) /
off_t st_size; /
total size, in bytes /
blksize_t st_blksize; /
blocksize for filesystem I/O /
blkcnt_t st_blocks; /
number of 512B blocks allocated /
time_t st_atime; /
time of last access /
time_t st_mtime; /
time of last modification /
time_t st_ctime; /
time of last status change */
};

eg:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main (int argc, char **argv)
{
struct stat stbuf;

stat(“stat.c”, &stbuf);
printf(“File Mode: %o Real Size: %luB, Space Size: %luB\n”, stbuf.st_mode, stbuf.st_size,
stbuf.st_blksize);

return 0;
}
[email protected]:~/apue$ gcc stat.c
[email protected]:~/apue$ ./a.out
File Mode: 100664 Real Size: 318B, , Space Size: 4096B

7.access():用來測試其許可權位
int access(const char *path,int mode);
path:路徑
mode有R_OK讀許可權,W_OK寫許可權,X_OK執行許可權,F_OK檢視檔案是否存在
eg:
#include <stdio.h>
#include <unistd.h>
#define TEST_FILE “access.c”
int main(void)
{
if( access(TEST_FILE, F_OK)!=0 )
{
printf(“File %s not exist!\n”, TEST_FILE);
return 0;
}
printf(“File %s exist!\n”, TEST_FILE);
if(access(TEST_FILE, R_OK)==0)
printf(“READ OK\n”);
if(access(TEST_FILE, W_OK)==0)
printf(“WRITE OK\n”);
if(access(TEST_FILE, X_OK)==0)
printf(“EXEC OK\n”);
return 0;
}

執行及結果:
[email protected]:~/apue$ gcc access.c
[email protected]:~/apue$ ./a.out
File access.c exist!
READ OK
WRITE OK

8.unlike() :可用來刪除檔案,其本質是讓連結字數自減;關閉檔案時,會先檢查其程序個數如果為0,再檢查連結個數,也為0的話則刪除

9rename():檔案重新命名
int renmae(const char *newname,const char *oldnme)

10.linux下對檔案的一些操作

int mkdir(const char *pathname,mode_t mode):建立檔案
int rmdir(const char *path):刪除檔案
DIR opendir(const char *path):開啟檔案
struct dirent *readir(const char *path):讀檔案