2013-08-06 20 views
6

Những gì tôi muốn làmchuyển hướng stdout/stderr nộp theo unix C++ - một lần nữa

chuyển hướng stdout và stderr đến một hoặc nhiều tập tin từ bên trong C++

Tại sao tôi cần nó

Tôi đang sử dụng thư viện bên thứ ba được biên dịch sẵn bên ngoài, tạo ra một lượng đầu ra vô lý, mà tôi muốn chuyển hướng đến tệp nhật ký để giữ cho bàn điều khiển luôn sạch sẽ.

Điều kiện

Compatibility không phải là một vấn đề, mã sẽ chỉ chạy trên các hệ thống Unix. Chuyển hướng không chỉ ảnh hưởng đến in ấn C++ - style (std :: cout < < "hello world" < < std :: endl), mà còn in c-style (printf ("hello world \ n")).

Những gì tôi đã cố gắng cho đến nay

Tôi đã được duyệt trên stackoverflow cho nửa ngày, đọc nhiều câu trả lời cho những người gặp vấn đề tương tự. Với sự giúp đỡ của những câu trả lời, tôi đã có thể cùng nhau đưa các đoạn mã sau:


#include <stdio.h> 
#include <iostream> 
#include <fcntl.h> 
#include "unistd.h" 

const int stdoutfd(dup(fileno(stdout))); 

int redirect_stdout(const char* fname){ 
    fflush(stdout); 
    int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP |  S_IROTH); 
    dup2(newstdout, fileno(stdout)); 
    close(newstdout); 
} 

int restore_stdout(){ 
    fflush(stdout); 
    dup2(stdoutfd, fileno(stdout)); 
    close(stdoutfd); 
    return stdoutfd; 
} 

int main(){ 
    redirect_stdout("/dev/null"); 
    std::cout << "invisible 1" << std::endl; 
    restore_stdout(); 
    std::cout << "visible 1" << std::endl; 
    redirect_stdout("/dev/null"); 
    std::cout << "invisible 2" << std::endl; 
    restore_stdout(); 
    std::cout << "visible 2" << std::endl; 
    return 0; 
} 

Những gì tôi mong chờ để xem:

visible 1 
visible 2 

Những gì tôi thực sự xem

visible 1 

Tức là, khi sử dụng cơ chế cho lần đầu tiên, nó hoạt động - nhưng nếu được sử dụng một lần nữa, khôi phục đầu ra sẽ không hoạt động. Ai đó có thể chỉ ra cho tôi những gì tôi cần thay đổi để có cơ chế hoạt động vô hạn?

+0

có thể trùng lặp: http://stackoverflow.com/questions/4810516/c-redirecting-stdout – Kelm

Trả lời

4

Nếu bạn muốn có thể sử dụng lại, đừng đóng stdoutfd trong restore_stdout.

1

Bạn đang tìm kiếm một cái gì đó như thế này: -

int main() 
{ 
    // Save original std::cin, std::cout 
    std::streambuf *coutbuf = std::cout.rdbuf(); 
    std::streambuf *cinbuf = std::cin.rdbuf(); 

    std::ofstream out("outfile.txt"); 
    std::ifstream in("infile.txt"); 

    //Read from infile.txt using std::cin 
    std::cin.rdbuf(in.rdbuf()); 

    //Write to outfile.txt through std::cout 
    std::cout.rdbuf(out.rdbuf()); 

    std::string test; 
    std::cin >> test;   //from infile.txt 
    std::cout << test << " "; //to outfile.txt 

    //Restore back. 
    std::cin.rdbuf(cinbuf); 
    std::cout.rdbuf(coutbuf); 

} 

Từ của tôi trước đó answer

+1

nhờ cho câu trả lời của bạn - tuy nhiên, tôi phải nói rằng tôi đã muốn chuyển hướng không chỉ C++ - các câu lệnh in kiểu, nhưng cũng có các câu lệnh in plain-c sử dụng printf - trong đó, afaik, giải pháp của bạn không thực hiện được. xin lỗi vì sự không chính xác, tôi đã chỉnh sửa câu hỏi cho phù hợp. – carsten

0

Đối iostreams C++, bạn có thể sử dụng sự quá tải không const của rdbuf thiết std::cout đến một std::filebuf. (Điều này được thực hiện tốt nhất bởi phương tiện của một lớp RAII, vì bạn phải khôi phục nó trước khi rời khỏi chính.) Đối với C FILE*, bạn có thể sử dụng freopen, nhưng Tôi không nghĩ rằng bạn sẽ có thể khôi phục nó.

FWIW: cả hai giải pháp này chỉ sử dụng tiêu chuẩn C++ hoặc C, do đó, nên được di chuyển.

1

cũng i u'd sử dụng freopen tốt hơn()

Cách sử dụng Cú pháp:

freopen("RedToFile","r",stdout); 
or 
freopen("/dev/null","a",stdout); 

cùng đi cho "stderr"

0

Ngoài afr0ck câu trả lời của freopen() tôi muốn nói trong khi sử dụng freopen(), chúng ta nên cẩn thận. Khi một luồng như stdout hoặc stdin được mở lại với việc gán đích mới (tại đây tệp 'output.txt') luôn luôn là một chương trình trừ khi nó đã được thay đổi rõ ràng.

freopen("output.txt", "a", stdout); 

Đây là dòng đầu ra tiêu chuẩn stdout được mở cửa trở lại và được giao 'output.txt' tập tin. Sau đó bất cứ khi nào chúng tôi sử dụng printf() hoặc bất kỳ luồng nào khác stdout như - putchar() thì mọi đầu ra sẽ chuyển đến 'output.txt'. Để lấy lại hành vi mặc định (có nghĩa là in ra trong giao diện điều khiển/thiết bị đầu cuối) của printf() hay putchar() chúng ta có thể sử dụng các dòng mã sau đây -

  • cho gcc, phân phối Linux như Ubuntu - freopen("/dev/tty", "w", stdout);
  • cho MinGW C/C++, cửa sổ - freopen("CON", "w", stdout);

Xem ví dụ mã dưới đây -

#include <stdio.h> 

int main() { 

    printf("No#1. This line goes to terminal/console\n"); 

    freopen("output.txt", "a", stdout); 
    printf("No#2. This line goes to the \"output.txt\" file\n"); 
    printf("No#3. This line aslo goes to the \"output.txt\" file\n"); 

    freopen("/dev/tty", "w", stdout); /*for gcc, diffrent linux distro eg. - ubuntu*/ 
    //freopen("CON", "w", stdout); /*Mingw C++; Windows*/ 
    printf("No#4. This line again goes to terminal/console\n");   

} 

này mã tạo ra tệp 'output.txt' trong thư mục hiện tại của bạn và số # 2 và số 3 sẽ được in trong tệp 'output.txt'.

Cảm ơn

Các vấn đề liên quan