5.6 每次读写一个字符的I/O
- 函数声明
int fgetc(FILE *stream); // man fgetc int fputc(int c, FILE *stream); // cast int c to char and write to stream
- 简单的Demo使用fgetc和fputc
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv) { FILE *fps, *fpd; int ch; if (argc < 3) { fprintf(stderr, "usage: %s <src_file> <dest_file>", argv[0]); } fps = fopen(argv[1], "r"); //需要fps存在 if (fps == NULL) { perror("fps error"); exit(1); } fpd = fopen(argv[2], "w"); if (fpd == NULL) { fclose(fps); perror("fpd error"); exit(1); } while (1) { ch = fgetc(fps); if (ch == EOF) //读到文件尾 break; fputc(ch, fpd); //打印独到的内容到fpd } fclose(fpd); fclose(fps); exit(0); }
测试文件字符个数, 通过fgetc()实现,达到和ll命令一样的效果
int main(int argc, char **argv) { FILE *fps; int ch; if (argc < 2) { fprintf(stderr, "usage: %s <src_file>", argv[0]); } fps = fopen(argv[1], "r"); //需要fps存在 read only if (fps == NULL) { perror("popen()"); exit(1); } int count = 0; while (fgetc(fps) != EOF) { count++; } printf("count = %d\n", count); fclose(fps); exit(0); }
5.7 每次读写一行的I/O
- 函数定义
char *fgets(char *s, int size, FILE *stream); //从stream每次读size大小的数据到s int fputs(const char *s, FILE *stream); // write char* s to stream
(1)gets(char* s) 是不安全的,因为仅传入一个地址,所以可能会读不完整或者读越界。所以引入fgets函数
(2)fgets需要注意:当读到size -1位置的数据
比如:
char buf [5]; fgets(buf, 5 ,stream); //1. 那么读取 abcdef 怎么读呢? // 为 a b c d \0 然后下次从e开始读 // 那么读取 ab 那么为 a b \0 //2. 那么读abcd 需要读几次呢? // a b c d \0 然后下一次读 \n \0 ...故要两次
- Demo:fgets和fputs实现文件的拷贝
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFFERSIZE 1024 int main(int argc, char **argv) { FILE *fps, *fpd; char buff[BUFFERSIZE]; if (argc < 3) { fprintf(stderr, "usage: %s <src_file> <dest_file>", argv[0]); } fps = fopen(argv[1], "r"); //需要fps存在 if (fps == NULL) { perror("fps error"); exit(1); } fpd = fopen(argv[2], "w"); if (fpd == NULL) { fclose(fps); perror("fpd error"); exit(1); } while (NULL != fgets(buff, BUFFERSIZE, fps)) { fputs(buff, fpd); } fclose(fpd); fclose(fps); exit(0); }
5.9 直接I/O, 操作一个对象(一般是一个文件)
- 函数定义
//从stream读nmemb个大小为size的数据到ptr,返回值为读取成功的对象个数 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); //写nmemb个大小为size的的数据ptr到stream size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
注意fread读取的时候:注意当读取的内容小于size个的情况。
比如:
fread(buf, 1, 10, fp); fread(buf, 10, 1, fp); // 使用fread(buf, 10, 1, fp);读取,若对象只有5个字节大小,则返回值为 0。 // 所以为了保险使用fread(buf, 1, 10, fp);可保证每个字节都被读到
所以fread和fwrite一般用于整块整块的文件读写。但这又需要保证数据没有问题,否则中间错了,后面就都错了。
- Demo: 实现文件的拷贝
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFFERSIZE 1024 int main(int argc, char **argv) { FILE *fps, *fpd; char buff[BUFFERSIZE]; if (argc < 3) { fprintf(stderr, "usage: %s <src_file> <dest_file>", argv[0]); } fps = fopen(argv[1], "r"); //需要fps存在 if (fps == NULL) { perror("fps error"); exit(1); } fpd = fopen(argv[2], "w"); if (fpd == NULL) { fclose(fps); perror("fpd error"); exit(1); } size_t n; while ((n = fread(buff, 1, BUFFERSIZE, fps)) > 0) { fwrite(buff, 1, n, fpd); } fclose(fpd); fclose(fps); exit(0); }