1 Linux file read and write


Preface (including table of contents)


Linux default file descriptor number is 1024,
available command view

ulimit -n

The first three are occupied by default

// stdin
#define STDIN_FILENO	0;
// stdout
#define STDOUT_FILENO	1;
// stderr
#define STDERR_FILENO	2;
/**
 * @author IYATT-yx
 * @brief 读取一个文件,并写入另外一个文件(不存在则创建)
 */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    
    
    if (argc != 3)
    {
    
    
        printf("请指定两个参数,分别为 [源文件] [目标文件]\n");
        return -1;
    }
    
    // 打开源文件,若执行失败,open内部会设置 errno 值,并返回 -1
    // perrno根据 errno 的值,输出对应错误信息
    int fdRead = open(argv[1], O_RDONLY);
    if (fdRead == -1)
    {
    
    
        perror("read file");
        return -1;
    }

    // 打开或不存在就创建将要写入的目标文件
    // 指定生成的文件权限为 0664 ,实际文件的权限为 0664 & ~umask
    int fdWrite = open(argv[2], O_WRONLY | O_CREAT, 0664);
    if (fdWrite == -1)
    {
    
    
        perror("write file");
        return -1;
    }

    char buf[4096];
    ssize_t len;

    // 从文件描述符 fdRead 读取 buf 容量大小的数据到 buf 中, 返回值为实际读取的数据长度, 返回 0 读完,返回 -1 失败
    while ((len = read(fdRead, buf, sizeof(buf))) > 0)
    {
    
    
        // 将 buf 中 len 长度的数据写入 fdWrite 文件描述符对应打开的文件, 返回 -1 代表失败!
        ssize_t ret = write(fdWrite, buf, (size_t)len);
        if (ret == -1)
        {
    
    
            perror("write");
            return -1;
        }
    }

    // 关闭文件描述符
    close(fdRead);
    close(fdWrite);
}

Move the file pointer to the head

lseek(fd, 0, SEEK_SET);

Get the current position of the file pointer

off_t idx = lseek(fd, 0, SEEK_CUR);

Get file length

off_t len = lseek(fd, 0. SEEK_END);

File expansion (for example, you can create a blank file when you start downloading, and expand the local download file to the same size according to the size of the file to be downloaded to occupy the space, and then replace the expanded and filled data from the beginning when downloading)

// 拓展 1KB 大小
off_t size = 1024;
lseek(fd, size, SEEK_END);
// 拓展后进行write才有效,写入内容任意,比如这里以空格结尾
const char *str = " ";
write(fd, str, 1);



/**
 * @author IYATT-yx
 * @brief 阻塞读终端
 */
#include <stdio.h>
#include <unistd.h>

int main(void)
{
    
    
    char buf[5];
    ssize_t len = read(STDIN_FILENO, buf, 5);
    if (len == -1)
    {
    
    
        perror("open STDIN_FILENO");
        return -1;
    }
    write(STDOUT_FILENO, buf, (size_t)len);
}

After compiling and executing this program, the terminal will wait for user input and stop at the read function until the input is pressed and enter, and the first five of the input (less than 5 characters are the actual input number) are read into buf , The next step is to execute write to print out the content of buf to the terminal.
When the input characters are within 5 set by read, there may be no difference, but if the input data exceeds 5, you may see another phenomenon. The first 5 characters will be output normally, and the following characters will be displayed after the command prompt and be executed as a command. The reason for this phenomenon: When the program here is executed, the program acts as the foreground and the terminal switches to the background. This program only obtains the first 5 characters and outputs the obtained characters. After completion, the program ends, the terminal is switched to the foreground, and the excess characters input when the program is executed are accepted and executed at the same time.
Insert picture description here

/**
 * @author IYATT-yx
 * @brief 非阻塞读终端
 */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <errno.h>

int main(void)
{
    
    
    int fdRead = open("/dev/tty", O_RDONLY | O_NONBLOCK);
    if (fdRead == -1)
    {
    
    
        perror("open /dev/tty");
        return -1;
    }
    char buf[4];
    ssize_t len;
    while (true)
    {
    
    
        len = read(fdRead, buf, sizeof(buf));
        if (len == -1)
        {
    
    
            if (errno == EAGAIN)
            {
    
    
                printf("请重试!\n");
                sleep(3);
                continue;
            }
            perror("read /dev/tty");
            return -1;
        }
        write(STDOUT_FILENO, buf, (size_t)len);
        close(fdRead);
        return 0;
    }
}

In the non-blocking read terminal, when there is no input, it will not stop at the read position and wait for input but continue to execute.

ps:
The attributes of ordinary files are not blocked by default.
Terminal devices, pipes, and socket files are blocked by default


Copy file descriptor:
dupFunction: Return the new file descriptor (the smallest unoccupied) that also points to the file pointed to by the original file descriptor
dup2Function: You can specify the new file descriptor to point to the file pointed to by the original file descriptor

Guess you like

Origin blog.csdn.net/weixin_45579994/article/details/112690496