1--I/O分类
sysio:称为系统调用IO(文件IO);
stdio:称为标准IO(标准IO基于系统调用IO来实现,其移植性好,一般优先调用)
2--fopen()
通过 man 手册来查看 fopen 的使用;
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(){
FILE *fp;
fp = fopen("tmp", "r"); // read not create
if(fp == NULL){
// fprintf(stderr, "fopen() failed! errno = %d\n", errno);
perror("fopen()");
// fprintf(stderr, "fopen():%s\n", strerror(errno));
exit(1);
}
puts("OK!");
fclose(fp);
exit(0);
}
vim fopen.c
make fopen
./fopen
查看单个线程能够打开的最大文件个数:ulimit -a(结果为 1024 个)
3--fclose()
fclose 用于关闭一个流,可通过 man 手册查看其用法;
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(){
FILE *fp;
fp = fopen("tmp", "r"); // read not create
if(fp == NULL){
// fprintf(stderr, "fopen() failed! errno = %d\n", errno);
perror("fopen()");
// fprintf(stderr, "fopen():%s\n", strerror(errno));
exit(1);
}
puts("OK!");
fclose(fp);
exit(0);
}
4--文件权限
文件权限: 0666 & ~umask,其中 umask 为 0002;
可通过 ll 查看文件的访问权限;
5--fgetc()和fputc()
fgetc() 从指定流获取一个字符,fputc() 将字符输出到指定流中,可通过 man 手册查看 fgetc() 和 fputc() 的用法;
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
if(argc < 3){
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
exit(1);
}
FILE* fps, *fpd;
fps = fopen(argv[1], "r");
if(fps == NULL){
fclose(fps);
perror("fopen()");
exit(1);
}
fpd = fopen(argv[2], "w");
if(fpd == NULL){
perror("fopen()");
exit(1);
}
while(1){
int ch = fgetc(fps); // 从fps读取一个字符
if(ch == EOF) break;
fputc(ch, fpd); // 将读取的字符写入fpd
}
fclose(fpd);
fclose(fps);
exit(0);
}
6--fgets()和fputs()
fgets() 从指定流获取字符串,fputs() 将字符串输出到指定流中,可通过 man 手册查看 fgets() 和 fputs() 的用法;
// 用法
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
// 伪代码
#define SIZE 5
char buf[SIZE];
fgets(buf, SIZE, stream);
// 假设 stream 的内容是 abcdef,读取 SIZE - 1 个字节,因为第 SIZE 个字节存取'\0'
// 则 fgets() 第一次读取的内容是: a b c d '\0',下一次从 e 开始读取
// 假设 stream 的内容是 ab
// 则 fgets() 可以一次读完,读取的内容为 a b '\n' '\0'
// 假设 stream 的内容是 abcd
// 则 fgets() 需要两次读完所有内容,第一次读取:a b c d '\0'
// 第二次读取: '\n' '\0' ...
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1024
int main(int argc, char *argv[]){
if(argc < 3){
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
exit(1);
}
FILE* fps, *fpd;
fps = fopen(argv[1], "r");
if(fps == NULL){
fclose(fps);
perror("fopen()");
exit(1);
}
fpd = fopen(argv[2], "w");
if(fpd == NULL){
perror("fopen()");
exit(1);
}
char buf[SIZE];
while(fgets(buf, SIZE, fps)){ // 从 fps 中读取 SIZE-1 个字节,存放在buf中
fputs(buf, fpd); // 将 buf 的内容写入 fpd 中
}
fclose(fpd);
fclose(fps);
exit(0);
}
7--fread()和fwrite()
fread() 和 fwrite() 用于从指定流读取和写入数据,可通过 man 手册查看其用法;
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
// 从 stream 中读取 nmemb 个对象,每个对象的大小为 size 字节,将读取的内容放到 ptr 中;
// fread() 一般是按单个字节来读取,即 size 的参数为 1
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
// On success, fread() and fwrite() return the number of items read or written.
// 即返回写入了或者读取了多少个数据
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1024
int main(int argc, char *argv[]){
if(argc < 3){
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
exit(1);
}
FILE* fps, *fpd;
fps = fopen(argv[1], "r");
if(fps == NULL){
fclose(fps);
perror("fopen()");
exit(1);
}
fpd = fopen(argv[2], "w");
if(fpd == NULL){
perror("fopen()");
exit(1);
}
char buf[SIZE];
int n;
// 从 fps 中每次读取 SIZE 个字节,将其存放在buf中
// 返回结果是:实际上读取的字节数,即 n
// 当读取的字节数 n > 0 时,继续读取
while((n = fread(buf, 1, SIZE, fps)) > 0){
// 读到 n 个对象,写入 n 个对象,因为fps中实际的字节数不一定是 SIZE 的整数倍
// 最后一次读取,读到的字节数可能会小于 SIZE
fwrite(buf, 1, n, fpd); // 从 buf 中将 n 个字节写入 fpd
}
fclose(fpd);
fclose(fps);
exit(0);
}