APUE---chap5标准I/O---5.6 5.7 5.9(fgetc/fputc/fgtes/fputs/fwrite/fread)

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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值