Linux--文件(2)-重定向和文件缓冲

命令行中的重定向符号

介绍和使用

在Linux的命令行中,重定向符号用于将命令的输入或输出重定向到文件或设备

常见的重定向符号:

1.">"符号:将命令的标准输出重定向到指定文件中,并覆盖原有的内容。

2.">>"符号:将命令的标准输出重定向的指定文件中,并将输出结果追加到文件末尾。

3."<"符号:将指定文件的内容作为命令的标准输入。

4."<<"符号:将命令的标准输入设置为指定的文本块。

在使用重定向符号时,应该确保文件或设备的权限设置正确,否则可能会出现无法访问或写入的错误

模拟实现

下面通过自定义shell来进行模拟实现重定向,加深印象。

自定义Shell的链接入口




文件缓冲问题

描述

文件缓冲是指将数据暂时存储在内存中,而不是立即写入到文件中 。这样可以提高文件操作的效率,因为将多次的写操作合并为一次,可以减少IO操作的效率。

文件缓冲主要为两种类型:

  • 全缓冲:当填满缓冲区或遇到换行符时,才会执行写操作。例如,使用fwrite()函数写入数据时,默认是全缓冲。
  • 行缓冲:当遇到换行符时,才会执行写操作。例如,使用printf()函数输出数据时,默认是行缓冲。

可以使用setbuf()setvbuf()等函数来设置文件的缓冲方式。此外,使用fflush()函数可以强制刷新缓冲区,将缓冲区中的数据立即写入到文件中。

需要注意的是,文件缓冲只适用于标准I/O库函数(如stdio.h中的函数),对于直接使用系统调用进行文件操作的函数(如read()write()),没有文件缓冲的概念,数据会立即写入文件。


例子



模拟实现

头文件:mystdio.h

c 复制代码
#pragma once

#include <stdio.h>

#define SIZE 4096
#define NONE_FLUSH (1<<1) 
#define LINE_FLUSH (1<<2) 
#define FULL_FLUSH (1<<3) 

typedef struct _myFILE
{
    //char inbuffer[];
    char outbuffer[SIZE];
    int pos;
    int cap;
    int fileno;
    int flush_mode;
}myFILE;


myFILE *my_fopen(const char *pathname, const char *mode);
int my_fwrite(myFILE *fp, const char *s, int size);
//int my_fread();
void my_fflush(myFILE *fp);
void my_fclose(myFILE *fp);
void DebugPrint(myFILE *fp);

源文件:mystdio.c

c 复制代码
#include "mystdio.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

const char *toString(int flag)
{
    if(flag & NONE_FLUSH) return "None";
    else if(flag & LINE_FLUSH) return "Line";
    else if(flag & FULL_FLUSH) return "FULL";
    return "Unknow";
}

void DebugPrint(myFILE *fp)
{
    printf("outbufer: %s\n", fp->outbuffer);
    printf("fd: %d\n", fp->fileno);
    printf("pos: %d\n", fp->pos);
    printf("cap: %d\n", fp->cap);
    printf("flush_mode: %s\n", toString(fp->flush_mode));
}

myFILE *my_fopen(const char *pathname, const char *mode)
{
    int flag = 0;
    if(strcmp(mode, "r") == 0)
    {
        flag |= O_RDONLY;
    }
    else if(strcmp(mode, "w") == 0)
    {
        flag |= (O_CREAT|O_WRONLY|O_TRUNC);
    }
    else if(strcmp(mode, "a") == 0)
    {
        flag |= (O_CREAT|O_WRONLY|O_APPEND);
    }
    else
    {
        return NULL;
    }

    int fd = 0;
    if(flag & O_WRONLY)
    {
        umask(0);
        fd = open(pathname, flag, 0666);
    }
    else
    {
        fd = open(pathname, flag);
    }
    if(fd < 0) return NULL;

    myFILE *fp = (myFILE*)malloc(sizeof(myFILE));
    if(fp == NULL) return NULL;
    fp->fileno = fd;
    fp->cap = SIZE;
    fp->pos = 0;
    fp->flush_mode = LINE_FLUSH;

    return fp;
}

void my_fflush(myFILE *fp)
{
    if(fp->pos == 0) return;
    write(fp->fileno, fp->outbuffer, fp->pos);
    fp->pos = 0;
}

int my_fwrite(myFILE *fp, const char *s, int size)
{
    // 1. 写入
    memcpy(fp->outbuffer+fp->pos, s, size);
    fp->pos += size;

    // 2. 判断,是否要刷新
    if((fp->flush_mode & LINE_FLUSH) && fp->outbuffer[fp->pos-1] == '\n')
    {
        my_fflush(fp);
    }
    else if((fp->flush_mode & FULL_FLUSH) && fp->pos  == fp->cap)
    {
        my_fflush(fp);
    }
    return size;
}

void my_fclose(myFILE *fp)
{
    my_fflush(fp);
    close(fp->fileno);
    free(fp);
}





测试:

相关推荐
AlfredZhao3 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334669 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪10 小时前
linux 拷贝文件或目录到指定的位置
linux
大树881 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush41 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5201 天前
Linux 11 动态监控指令top
linux
小宇宙Zz1 天前
Maven依赖冲突
java·服务器·maven
不会C语言的男孩1 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈1 天前
Unix 与 Linux 异同小叙
linux·服务器·unix