Linux下可以通过系统调用来读写文件,也可以通过标准函数库来读写文件。1) 系统调用
open() 声明: #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> //Linux系统不需要这个头文件 int open(const char *path, int oflags); int open(const char *path, int oflags, mode_t mode); oflags参数: 当调用open系统调用的时候,下面三个参数,必须要选择一个作为参数: O_RDONLY // 打开的文件只能读 O_WRONLY // 打开的文件只能写 O_RDWR // 打开的文件可以读也可以写 除了上面的参数,还可以添加一下参数(他们是可选的): O_APPEND // 写文件的时候从文件尾开始写 O_TRUNC // 清空文件内容 O_CREAT // 创建文件 O_EXCL // 当存在O_CREAT参数的时候,O_EXCL确保只有在文件不存在的时候才建立文件 mode参数: 只有在oflags参数中含有O_CREAT才使用下面的参数 S_IRUSR // 建立文件时,权限设置为创建文件的用户可读 S_IWUSR // 建立文件时,权限设置为创建文件的用户可写 S_IXUSR // 建立文件时,权限设置为创建文件的用户可执行 S_IRGRP // 建立文件时,权限设置为创建文件的用户所在组的所有用户可读 S_IWGRP // 建立文件时,权限设置为创建文件的用户所在组的所有用户可写 S_IXGRP // 建立文件时,权限设置为创建文件的用户所在组的所有用户可执行 S_IROTH // 建立文件时,权限设置为其他用户可以读 S_IWOTH // 建立文件时,权限设置为其他用户可以写 S_IXOTH // 建立文件时,权限设置为其他用户可以执行 注意,创建出来的文件权限不一定和这里设置的一模一样,因为umask会影响权限的值,详细参考:http://www.i170.com/user/killercat/Article_54617 中的(3)访问权限 返回值: 返回值是一个文件描述符,-1表示open()调用失败 范例: int f = open("/home/killercat/Desktop/1",O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); // 打开/home/killercat/Desktop/1文件,建立的文件权限设置成用户可读可写(这个和umask有关) int f = open("/home/killercat/Desktop/1",O_RDWR); // 打开一个文件,可读也可以写 write() 声明: #include <unistd.h> size_t write(int fildes, const void *buf, size_t nbytes); 读取buf数组中长度为nbytes个字节的数据到fildes文件描述符,表示的文件中去,返回值为真正写入了多少字节的数据 范例: write(1,"hello world",5); // 在文件描述符1表示的文件中写入"hello",实际上就是在屏幕打印hello int f = open("/home/killercat/Desktop/1",O_RDWR); write(f,"hello world",11); // 向/home/killercat/Desktop/1中写入"hello world" read() 声明: #include <unistd.h> size_t read(int fildes, const void *buf, size_t nbytes); 读取文件描述符fides表示的文件中长度为nbytes字节的数据到 buf 数组中去,返回为实际读的数据的长度,注意从什么位置开始读取数据,有一个指针决定,文件指针可以通过lseek()系统调用修改,刚被打开的文件中,文件指针指向文件首位置 范例: char buf[1024]; int f = open("/home/killercat/Desktop/1",O_RDWR); read(f,buf,11); // 读取文件"/home/killercat/Desktop/1"中11个字节,保存到buf中去,注意一下,读取的是字节,也就是一个中文字,应该读取2个字节(gbk编码) close() 声明: #include <unistd.h> int close(int fildes); 关闭文件描述符为fides的文件,成功时返回0,失败返回-1。注意,进程被结束的时候,与之有关的文件都会被关闭,我们这时候不需要调用close(); 范例: int f = open("/home/killercat/Desktop/1",O_RDWR); close(f); 使用系统调用,写一个复制文件的程序 #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> int main(){ int fin,fout; char buf[1024]; // 之所以用char类型,是因为 read write 的单位是字节 fout = open("/home/killercat/Desktop/llh(2).mp3", O_CREAT|O_WRONLY|O_TRUNC|O_EXCL,S_IRUSR|S_IWUSR); fin = open("/home/killercat/Desktop/llh.mp3",O_RDONLY); if(fin == -1 || fout == -1) return -1; int len; while((len=read(fin,buf,sizeof(buf)))>0) write(fout,buf,len); close(fin); close(fout); return 0; } 2) 库函数: fopen() 声明: #include <stdio.h> FILE *fopen(const char *filename, const char *mode); 通过路径或者文件名字打开一个文件,打开需要设置一定的模式,返回一个FILE类型的结构体指针 mode参数: "r" // 打开文件只能用于读,文件不存在,调用就会失败,返回值为 NULL "w" // 打开文件只能用于写,文件不存在就被创建一个新文件,文件存在就清空里面的内容,写入数据从文件开始处开始 "a" // 打开文件只能用于写,文件不存在就被创建一个新文件,写入数据从文件结束处开始 "rb","wb","ab" // 表示使用的是二进制方式打开文件,有时候,如果没有使用二进制方式打开二进制文件,会导致读到的数据被破坏 "r+" // 打开的文件可以读也可以写,文件不存,调用就会失败,返回值为 null,写文件的位置为文件开头 "w+" // 打开文件可以读也可以写,文件不存在就被创建一个新文件,文件存在就清空里面的内容,写入数据从文件开始处开始 "a+" // 打开文件可以读也可以写,文件不存在就被创建一个新文件,写入数据从文件结束处开始 "rb+" "wb+" "ab+" // 二进制方式 请参考http://www.i170.com/user/killercat/Article_35858,它大概讲述了模式中,是否有“b”造成的影响 范例: FILE* fin = fopen("/home/killercat/Desktop/1","r+"); fwrite() 声明: #include <stdio.h> size_t fwrite(void *ptr, size_t size, size_t nitems, FILE *stream); 把ptr数组中的数据,写入stream对应的文件中,写入数据一共有size*nitems字节。 fwrite是通过记录(record)来处理写入数据,size,表示记录的大小,nitems表示记录的个数。 返回值是成功写入数据的组数,失败返回NULL 范例: char buf[1024]; FILE* fout = fopen("/home/killercat/Desktop/1","w+"); fwrite(buf,5,2,fout); 一共写入10个字节的数据 fread() 声明: #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); 把stream对应的文件中size*nitems个字节的数据写入ptr数组。 fread()也是通过记录(record)来处理数据的,size,表示记录的大小,nitems表示记录的个数。 返回值是成功读取数据的组数,失败返回NULL 范例: char buf[1024]; FILE* fin = fopen("/home/killercat/Desktop/1","w+"); fread(buf,5,2,fin); 一共读入10个字节的数据 close() #include <stdio.h> int fclose(FILE *fp); 关闭文件 fgetc() fputc() int fgetc(FILE *); fputc(int,FILE *); 一个字符一个字符的读写。而内部实现并不是这么做,库函数会一块一块的读(写)文件,每次读(写)一块,它们会被放到一个缓冲中去,然后再从缓冲中读取数据,直到数据全部读完,才继续读(写)一块文件,所以即使fgetc,fputc一次只读写一个字节,也不会影响效率,fgetc()返回EOF表示结束。 使用标准函数库,写一个复制文件的程序 #include <stdio.h> int main(){ FILE *fin,*fout; int c; fin = fopen("/home/killercat/Documents/Movie/天狗.rmvb","r"); fout = fopen("/home/killercat/Desktop/llh(2).mp3","w"); if(fin == NULL || fout == NULL) return -1; while((c=fgetc(fin)) != EOF){ fputc(c,fout); } fclose(fin); fclose(fout); return 0; }