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





测试:

相关推荐
旖旎夜光36 分钟前
Linux(13)(中)
linux·网络
威迪斯特1 小时前
CentOS图形化操作界面:理论解析与实践指南
linux·运维·centos·组件·图形化·桌面·xserver
一方热衷.1 小时前
在线安装对应版本NVIDIA驱动
linux·运维·服务器
独自归家的兔1 小时前
ubuntu系统安装dbswitch教程 - 备份本地数据到远程服务器
linux·运维·ubuntu
m0_694845571 小时前
tinylisp 是什么?超轻量 Lisp 解释器编译与运行教程
服务器·开发语言·云计算·github·lisp
ONE_SIX_MIX1 小时前
ubuntu 24.04 用rdp连接,桌面黑屏问题,解决
linux·运维·ubuntu
龙飞051 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
*小海豚*1 小时前
在linux服务器上DNS正常,但是java应用调用第三方解析域名报错
java·linux·服务器
June`1 小时前
muduo项目排查错误+测试
linux·c++·github·muduo网络库
消失的旧时光-19432 小时前
Linux 编辑器入门:nano 与 vim 的区别与选择指南
linux·运维·服务器