我正在尝试使用read
从stdin
读取并将读取的字节发送到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);
}
答案 0 :(得分:2)
因为当您阅读BUFFER_SIZE
时,您正在写num_read
个字节。
就这样做吧
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);
}
}
}
另外,使用大括号并避免过多的缩进,在这种情况下很难阅读。
答案 1 :(得分:0)
除了写错了大小之外,你的错误信息仍然是垃圾邮件,因为你将va_list
传递给了fprintf
,这并不是它的期望。您需要在那里拨打vfprintf
。