【问题标题】:C read function reading more bytes than requestedC读取函数读取比请求更多的字节
【发布时间】:2017-04-22 16:23:40
【问题描述】:

我正在尝试使用readstdin 读取数据并将读取的字节发送到stdout,并将文件作为参数传递(模仿tee 命令)。但是,当我执行时:

echo AAAAAAAAAA | ./tee -a file

我明白了

AAAAAAAAAA
Â7þ­hý6þ­hý¥g¢c¾ 
@ERROR: failed to write whole buffer (140726359686392 != 2880)

您可以看到read 返回的数字远大于请求的缓冲区大小。 write 写的也比请求的多,但是read 返回的数字随着每次执行而变化,writes 总是返回 2880,不管输入的大小。

代码如下:

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

#include <fcntl.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <unistd.h>

#include <string.h>

#define BUFFER_SIZE 64

extern int optind;

void exit_err(char *format, ...)
{
    va_list args;

    fflush(stdout);

    va_start(args, format);
    fprintf(stderr, format, args);
    va_end(args);

    fprintf(stderr, "\n");

    fflush(stderr);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    if (argc < 2 || strncmp(argv[1], "--help", 6) == 0)
        exit_err("USAGE: %s [-a] [OUTPUTFILE]", argv[0]);

    bool append = false;

    char opt;
    while ((opt = getopt(argc, argv, "a")) != -1) {
        switch (opt)
        {
            case 'a':
                append = true;
                break;
            default: /* ? */
                exit_err("USAGE: %s [-a] [OUTPUTFILE]", argv[0]);
        }
    }

    if (optind >= argc) {
        exit_err("ERROR: expected argument after options");
        exit(EXIT_FAILURE);
    }

    int open_flags = O_WRONLY | O_CREAT;
    if (append)
        open_flags |= O_APPEND;
    else
        open_flags |= O_TRUNC;

    mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP;

    int num_output_files = argc - optind + 1;
    int output_fd[num_output_files];
    output_fd[0] = STDOUT_FILENO;

    int i;
    for (i = 1; i < num_output_files; ++i, ++optind) {
        output_fd[i] = open(argv[optind], open_flags, permissions);
        if (output_fd[i] == -1)
            exit_err("ERROR: failed to open %s", argv[optind]);
    }

    ssize_t num_read, num_written;
    char buffer[BUFFER_SIZE];
    while ((num_read = read(STDIN_FILENO, buffer, BUFFER_SIZE)) > 0)
        for (i = 0; i < num_output_files; ++i)
            if ((num_written = write(output_fd[i], buffer, BUFFER_SIZE)) != num_read)
                exit_err("ERROR: failed to write whole buffer (%zd != %zd)", num_read, num_written);

    if (num_read == -1)
        exit_err("ERROR: failed to read from stdin");

    for (i = 0; i < num_output_files; ++i)
        if (close(output_fd[i]) == -1)
            exit_err("ERROR: failed to close file");

    exit(EXIT_SUCCESS);
}

【问题讨论】:

    标签: c io


    【解决方案1】:

    因为您在读取 ​​num_read 时正在写入 BUFFER_SIZE 字节。

    就这样吧

    while ((num_read = read(STDIN_FILENO, buffer, BUFFER_SIZE)) > 0) {
        for (i = 0; i < num_output_files; ++i) {
            if ((num_written = write(output_fd[i], buffer, num_read)) != num_read) {
                exit_err("ERROR: failed to write whole buffer (%zd != %zd)", num_read, num_written);
            }
        }
    }
    

    另外,使用大括号并避免过多的缩进级别,在这种情况下很难阅读。

    【讨论】:

      【解决方案2】:

      除了错误大小的写入之外,您的错误消息是垃圾,因为您将va_list 传递给fprintf,这是意料之外的。你需要在那里打电话给vfprintf

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-12
        • 2011-07-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多