Redirecting Output to a File in C

redirecting output to a file in C

This is the result of my testing things out with dup2

The more subtle point is remembering fflush at the right times :) Otherwise, you'll get very surprising results.

Also, prefer fileno instead of hardcoding 1 (stdout) 2 (stderr).

Redirecting stdin was left as an exercise for the reader

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
int out = open("cout.log", O_RDWR|O_CREAT|O_APPEND, 0600);
if (-1 == out) { perror("opening cout.log"); return 255; }

int err = open("cerr.log", O_RDWR|O_CREAT|O_APPEND, 0600);
if (-1 == err) { perror("opening cerr.log"); return 255; }

int save_out = dup(fileno(stdout));
int save_err = dup(fileno(stderr));

if (-1 == dup2(out, fileno(stdout))) { perror("cannot redirect stdout"); return 255; }
if (-1 == dup2(err, fileno(stderr))) { perror("cannot redirect stderr"); return 255; }

puts("doing an ls or something now");

fflush(stdout); close(out);
fflush(stderr); close(err);

dup2(save_out, fileno(stdout));
dup2(save_err, fileno(stderr));

close(save_out);
close(save_err);

puts("back to normal output");

return 0;
}

How to redirect program output to text file

A good start is not ignoring compiler warnings:

test.c: In function ‘main’:
test.c:42:13: warning: passing argument 4 of ‘fwrite’ makes pointer from integer without a cast [enabled by default]
fwrite(c, 1, sizeof(c), output);
^
In file included from test.c:1:0:
/usr/include/stdio.h:715:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘int’
extern size_t fwrite (const void *__restrict __ptr, size_t __size,
^

int and FILE* are not interchangable. If you use open, write with write. If you use fopen, write with fwrite.

Additionally, you never modify stdout of your process. Instead you modify output, which doesn't make sense. Here are the minimum changes to your code to make it work:

#include <stdio.h>                                                                                                                                                                                                                                                                                                                                                                                                                       
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
int fd[2];
int processId;
int output;
char filename[] = "output.txt";

if((output = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1){
fprintf(stderr, "Unable to create/open file '%s'\n", filename);
return 1;
}

if(pipe(fd) == -1){
fprintf(stderr, "Error creating pipe\n");
return 2;
}

if((processId = fork()) == -1){
fprintf(stderr, "Error forking\n");
return 3;
}

if(processId == 0){
int newFD = dup(STDOUT_FILENO);
char newFileDescriptor[2];
sprintf(newFileDescriptor, "%d", newFD);
dup2(fd[1], STDOUT_FILENO); // You want to modify STDOUT_FILENO
close(fd[0]);
execl("/bin/echo", "echo", newFileDescriptor, NULL); // switched to echo
}else{
close(fd[1]);
char c[10];
int r = read(fd[0], c, sizeof(char) * 10);

if(r > 0){
fprintf(stderr, "PIPE INPUT = %s", c);
write(output, c, r); // use write instead of fwrite
}
}
}

Here's the result of running it:

$ gcc test.c -o test
$ ./test
PIPE INPUT = 6
$ cat output.txt
6

How to redirect output to a file in C?


Online, it says that > redirects command output to a file, and I'm not sure exactly what "command output" means.

"command output" refers to the stdout (Standard Output) stream of the program.

Do note that some shell commands are not separate programs but are actually shell builtins, though they'll still support output redirection. On Windows, most shell commands (like dir and del) are built-ins whereas on Linux/BSD/etc most shell commands are separate programs (like ls and mkdir)

If your program calls puts( "foobar" ); then running ./name from Bash will display "foobar" in your terminal emulator. But if you run ./name > file.txt then the "foobar" text will be written to file.txt and it will not be displayed in your terminal emulator.

Try it with the ls command, for example: ls -al > files.txt. This works on Windows too (dir /s > files.txt).

I'm redirecting the output from my name.c file to the outputFileName.ext file. Does command output mean stdout?

Yes.

If so, which C keyword would I use to write information to the outputFileName.ext file from name.c as stdout?

You don't. This is a shell/OS feature and is not part of C.

Redirect stdout to a file

What your code essentially does is that you open a pipe, then fork the process and in the child process (in commented code) close stdout, duplicate the pipe to stdout and execute and ls command, and then (in non-commented code) write 4 bytes to the pipe. In the parent process, you read data from the pipe and wait for the completion of the child process.

Now you want to redirect stdout to a file. You can do that by opening a file using the open() system call and then duplicating that file descriptor to stdout. Something like (I haven't tested this so beware of bugs in the code):

int filefd = open("foo.txt", O_WRONLY|O_CREAT, 0666);
if (!fork()) {
close(1);//Close stdout
dup(filefd);
execlp("ls", "ls", NULL);
} else {
close(filefd);
wait(NULL);
}
return 0;

However, you can also use the freopen as suggested by the other answer.

However, I have several concerns of your code and of my modified code:

  • The pipe() and open() system calls can fail. You should always check for system call failure.

  • The fork() system call can fail. Ditto.

  • dup2() can be used instead of dup(); otherwise the code will fail if stdin is not open as it duplicates to the first available file descriptor.

  • The execlp() system call can fail. Ditto.

  • I think wait() can be interrupted by a signal (EINTR). It's recommended to wrap it around a wrapper that retries the system call if it's aborted by a signal (errno == EINTR).

Redirect output from function to File in C

using freopen should help you.

freopen("temp.txt", "a+", stdout);

After reopening the stdout with freopen() all output statement printf, putchar are redirected to file temp.txt. So after that any printf() statement will redirect it's output to the temp.txt file.

reference:
https://linux.die.net/man/3/freopen

Redirect C output to a txt file

The user input is stdin but you are redirecting only stdout to file. Hence you will see in the output.txt only what your program prints to stdout. If you want to print entered values, you have to print them after scanf.

In the example below, you should see also input values in your output.txt

printf("Enter float1: ");
scanf("%f", &float1);
printf("%f\n", float1);

Redirect output to txt file on multiple lines

The only line break you output is at the very end of your code. If you want line breaks in the output, output them wherever you want them, just as you did in the last line of code.

Redirect standard output to file and re-establish the standard output with function

I finally got the correct answer, so here is how to temporarily redirects the standard output to a file name "file", then executes the function f, then re-establishes the original standard output:


void redirect_stdout (void (*f)(void), char *file)
{
int fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0644);
int savefd = dup(1);
dup2(fd, 1);
f();
dup2(savefd, 1);
close(fd);
close(savefd);
}

Redirecting output to file then back to console in C++

Probably what you are looking for is rdbuf() as mentioned by doomista in the comments.

Here is a way to redirect Output.

#include <iostream>
#include <fstream>

int main()
{
/** backup cout buffer and redirect to out.txt **/
std::ofstream out("out.txt");

auto *coutbuf = std::cout.rdbuf();
std::cout.rdbuf(out.rdbuf());

std::cout << "This will be redirected to file out.txt" << std::endl;

/** reset cout buffer **/
std::cout.rdbuf(coutbuf);

std::cout << "This will be printed on console" << std::endl;

return 0;
}


Related Topics



Leave a reply



Submit