系统编程I/O

I/O操作是实现一切的基础

  • 标准io – stdio(库)
  • 系统调用io – sysio(文件io)
    优先使用标准io=

stdio:

  1. fopen man fopen
  2. fclose
  3. fgetc
  4. fputc
  5. fgets
  6. fputs
  7. fread
  8. fwrite
  • fseek
  • ftell
  • rewind

fflush

// begin / current / end of file
 // r r+ 是文件必须存在的,其他都会被创建
perror(const char *); // 将errno显示成出错信息,自动关联了errno变量00,比如perror("fopen");
// 输出错误流  strerror解析错误号的内容
fprintf(stderr, "fopen() %s\n", strerror(errno));
FILE *fopen(const char *pathname, const char *mode);

File* 这个指针指向哪里?
栈? 静态区?

  1. 看fopen函数可以理解,如果返回在栈里面,需要先声明临时变量,最后返回&file,但是这是临时变量,返回临时变量的地址是不对的,它会在返回之前被释放
  2. 静态区:如果在静态区,那么这个file变量仅仅会被声明一次,那么每打开一个文件,前一个打开的文件存储就会被冲掉,无法实现打开多个文件
  3. 因此这个file指针应该是指向堆的,这就是为什么fopen之后会对应一个fclose的原因,fclose里面做的就是释放堆的空间
    总结: 小技巧识别,一般情况下有一对操作 (open_close)的,是存放在堆上的,其他一般是在静态区

默认最多可以打开多少个文件
一个进程使用的时候,默认会打开三个流(标准输入, 输出,出错)


ulimit -a 命令中open files可更改

ll

新文件权限
0666 & -umask
比如此时umask是0002 那么使用0666 & -0002
&1就是值不变,&0就是那一位被消掉(设置为0)
结果就是2->010->取反101 即0处被消掉,即666->666-2=664
umask值越大,被消掉的权限越多,新文件权限越低

  1. fgetc
  2. fputc
// 复制文件操作
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    int ch;
    if (argc < 3)
    {
        fprintf(stderr, "useage: %s, <src_file> <dst_file>\n",argv[0]);
        exit(0);
    }
    
    FILE* fps = fopen(argv[1], "r");
    if (fps == NULL)
    {
        perror("fopen");
        exit(1);
    }
    FILE* fpd = fopen(argv[2], "w");
    if (fpd == NULL)
    {
        fclose(fps);
        perror("fopen");
        exit(1);
    }

    while (1)
    {
        ch = fgetc(fps);
        if (ch == EOF)
        {
            break;
        }

        fputc(ch, fpd);
    }
    fclose(fpd);
    fclose(fps);
    return 0;
}
fgets(*, size, stream)
// size -1  '\n'  会停止
fputs
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    int ch;
    if (argc < 3)
    {
        fprintf(stderr, "useage: %s, <src_file> <dst_file>\n",argv[0]);
        exit(0);
    }
    
    FILE* fps = fopen(argv[1], "r");
    if (fps == NULL)
    {
        perror("fopen");
        exit(1);
    }
    FILE* fpd = fopen(argv[2], "w");
    if (fpd == NULL)
    {
        fclose(fps);
        perror("fopen");
        exit(1);
    }

    char buf[1024];

    while (fgets(buf, 1024, fps) != NULL)
    {
        fputs(buf, fpd);
    }

    fclose(fpd);
    fclose(fps);
    return 0;
}

第三个变量是有多少个成员,第二个变量是每个成员的大小,一般设置为1,当作字符去做
返会成功个数 fread(void* ptr, size_t size, size_t mnum, FILE* stream); // 从stream读到ptr
fwrite

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    int ch;
    if (argc < 3)
    {
        fprintf(stderr, "useage: %s, <src_file> <dst_file>\n",argv[0]);
        exit(0);
    }
    
    FILE* fps = fopen(argv[1], "r");
    if (fps == NULL)
    {
        perror("fopen");
        exit(1);
    }
    FILE* fpd = fopen(argv[2], "w");
    if (fpd == NULL)
    {
        fclose(fps);
        perror("fopen");
        exit(1);
    }

    char buf[1024];

    int  n;
    while ((n = fread(buf, 1 , 1024, fps) != NULL) > 0) // 读到多少写多少 
    {
        fwrite(buf, 1, n fpd);
    }

    fclose(fpd);
    fclose(fps);
    return 0;
}
fprintf(输出的流, “”, 格式的变量);
fprintf(stderr, "usage:%s", args[0]);

sprintf(char* str_tar, const char *format…);


char buf[100];
sprintf(buf, "格式化输出". 格式化变量); // 串的大小不清楚,缓冲区大小不定  用snprintf弥补
puts(buf);

sprintf(buf, n, "", 格式化变量); // 可以容纳 n-1个字符
fscanf(流, “格式化”);

// 操作文件位置指针 文件在关闭之前,文件指针是随着操作变化的,只有关闭之后再打开,才会重新定位,
ftell(FILE*); // 定位文件中的一个位置,但是文件大小不超过2G
ftello(FILE*); // 定位文件中的一个位置,但是编译的时候需要添加编译的宏,#define _FILE_OFFSET_BITS 64
fseek(FILE* , off, 宏); // 哪个流 , 偏移多少, 相对头还是尾偏移
// 目前没有一个函数可以任意取多少个字符

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main(int argc, char** argv) 
{
    if (argc < 3)
    {
        sprintf(stderr, "usage:%s <src> <dst>", argv[1]);
        exit(1);
    }
    FILE * ptr = NULL;
    int count = 0;
    ptr = fopen(argv[1], "r");
    if (ptr == NULL)
    {
        perror("fopen");
        exit(1);
    }
    fseek(ptr, 0, SEEK_END); // 定个位到末尾

    fprintf(stdout, "%d\n", ftell(ptr)); // 输出当前指针位置
    fclose(ptr);

    return 0;
}

rewind(流); 使用之后,会将指针设置到文件首

fflush();

什么都不会打印,默认刷新缓冲是换行符,

int main()
{
    int  i;
    printf("before");

    while (1);

    printf("after");
    return 0;
}

int main()
{
    int  i;
    printf("before\n"); // 会输出
	// 或者使用printf("before");  fflush(stdout);
    while (1); // 后续不再输出

    printf("after");
    return 0;
}

缓冲区存在的作用,合并系统调用

  1. 行缓冲:换行时刷新/ 满了刷新/强制fflush刷新----stdout–因为是终端设备
  2. 全缓冲:满了刷新,/ 强制刷新—默认只要不是终端设备就是
  3. 无缓冲:比如stderr,需要立即输出内容
getline();

从stream中读取一行

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "usage\n");
        exit(1);
    }

    FILE* fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("fopen");
        exit(1);
    }
    char* linbuf;
    size_t linesize;

    // 段错误隐患, 初始化
    linbuf = NULL;
    linesize = 0;


    while (1)
    {
        // getline本质是malloc,后续增大会realloc,但是没有出现free操作,因此这里存在内存泄露风险, 一行多大都会malloc读出来
        // 但是这里是可控的,只有linesize这么大的大小
        if (getline(&linbuf, &linesize, fp) < 0)
        {
            break;
        }
        printf("%d\n", strlen(linbuf));
    }

    fclose(fp);
    return 0;
}
临时文件
  1. 如何不冲突的创建临时文件
  2. 及时销毁
    tmpnam 没有办法安全的创建
    tmpfile
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值