繼上一篇《進程通訊之一使用WM_COPYDATA C++及C#實現》,進程通訊之二將分為三篇文章講解如何使用管道技術來完成進程通訊功能。三篇文章目錄如下:
1.《進程通訊之二 管道技術第一篇 輸入輸出的重新導向》
2.《進程通訊之二 管道技術第二篇 匿名管道》
3.《進程通訊之二 管道技術第三篇 具名管道》
本篇將介紹輸入輸出的重新導向問題,先來看一個小小的執行個體,設有一個程式,該程式的輸入輸出為標準輸入輸出即從鍵盤上輸入,輸出到螢幕。現在要重新導向IME輸出,使程式從檔案中讀取資料,處理後輸出到檔案。程式碼如下(稱此程式為樣本程式):
#include <stdio.h>int main(){int n;while (scanf("%d", &n) != EOF) //標準輸入時,可按ctrl+z來輸入EOF{n *= 2;printf("%d\n", n);}}
試給出幾種不同的實現方法,另外如果沒有程式碼,只有可執行檔,又應該如何做了?
實現方法一使用C語言的freopen()函數
函數功能:重新導向控制台的輸入輸出
函數原型:
FILE *freopen(
const char *path,
const char *mode,
FILE *stream
);
函數說明:
第一個參數為檔案指標(也可以用來指向標準輸入輸出)。
第二個參數為開啟檔案,"w"表示寫,"r"表示讀,"a"表示追加。其它設定可以參考MSDN。
第三個參數為FILE類型的指標,傳入stdin表示標準輸入,傳入stdout表示標準輸出。
這樣用只要用簡單一句freopen("infile.txt", "r", stdin);就可以使程式中的scanf()函數從檔案中讀取資料作為輸入,同樣freopen("outfile.txt", "w", stdout);可以使程式中的printf()函數將輸出由標準輸出改成輸出到檔案。現在有個問題,將程式的輸入輸出重新導向到檔案後,還能改回到標準輸入輸出嗎?答案是可以的,對第一個參數傳入"CON"這個字串就可以了(linux為"/dev/console")。
下面就給出修改後的代碼:
//直接使用freopen()函數 來改變控制台的標準輸入輸出#include <stdio.h>int main(){//將控制台的標準輸入輸出改成從檔案中讀取寫入FILE *pFileRead = freopen("infile.txt", "r", stdin);FILE *pFileWrite = freopen("outfile.txt", "w", stdout);int n;while (scanf("%d", &n) != EOF){n *= 2;printf("%d\n", n);}fclose(pFileRead);fclose(pFileWrite);//回到到控制台的標準輸入輸出 windows為"CON" linux為"/dev/console"freopen("CON", "r", stdin);freopen("CON", "w", stdout); printf("Finish 輸入0表示結束:\n");do{scanf("%d", &n);}while (n != 0);return 0;}
運行結果如所示:
可以看出該程式的輸出輸入已經完成了重新導向。
實現方法2 使用C++的ifstream和ofstream類
有些場合使用類來完成輸入輸出的重新導向任務會更加方便和習慣一些。所幸C++中就有ifstream和ofstream這二個類來協助我們完成這一任務。這個二類的詳細功能就不細說了。下面介紹下如何使用這二個類來重新導向程式的輸入輸出(看的時候看慢點喔,不會會被很多類名給搞暈去^_^)。
這二個類可以以讀的方式和寫的方法開啟一個檔案(ifstream的首字母i就表示in,而ofstream的首字母o就表示out),在iosfwd檔案中找到:
typedef basic_ifstream<char, char_traits<char> > ifstream;
typedef basic_ofstream<char, char_traits<char> > ofstream;
然後可以在fstream檔案中找到basic_ifstream類是繼承於basic_istream類,basic_ofstream類是繼承於basic_ostream類。
然後再來看看C++中大家平常使用的cin和cout,可以在iostream檔案中找到cin和cout的定義,這二個實際是istream類型和ostream類型的變數:
extern _CRTIMPistream cin;
extern _CRTIMPostream cout;
然後在iosfwd檔案中可以找到:
typedef basic_istream<char, char_traits<char> > istream;
typedef basic_ostream<char, char_traits<char> > ostream;
明顯cin和cout與ifstream類和ofstream類有著非常密切關係——cin是basic_istream類的變數,而ifstream則是basic_istream類的衍生類別。cout是basic_ostream類的變數,而ofstream則是basic_ostream類的衍生類別。
有了這個後,猜測很可能會有某個成員函數能將它們聯絡到一起,從而讓cin和cout由標準輸入輸出重新導向到從檔案中讀取,輸出到檔案。事實上在basic_istream類實際是虛繼承於basic_ioso類,basic_ostream類實際是虛繼承於basic_ios類。這二個類都有個rdbuf()成員函數,這個函數允許我們訪問和修改類中一個類型為basic_streambuf類的成員變數。改動這個變數就能重新導向輸入輸出。因此對cin和cout調用這個rdbuf()函數並傳入ifstream和ofstream的rdbuf()就可以將控制台的標準輸入輸出改成從檔案中讀取和輸出到檔案。
OK,方法既然找到了,那下面就使用C++的方法來重新導向輸入輸出:
//使用ifstream和ofstream及cin和cout的rdbuf()#include <iostream>#include <fstream>using namespace std;int main(){printf(" 使用ifstream和ofstream及cin和cout的rdbuf()來改變控制台的標準輸入輸出\n"); printf(" --by MoreWindows( http://blog.csdn.net/MoreWindows )--\n\n"); //將控制台的標準輸入輸出改成從檔案中讀取寫入ifstream inFile("infile.txt");ofstream outFile("outfile.txt");//儲存原來的輸入輸出方式 streambuf類就是basic_streambuf類streambuf *strmin_buf = cin.rdbuf();streambuf *strmout_buf = cout.rdbuf();printf("開始處理檔案\n....\n");//重新導向到檔案cin.rdbuf(inFile.rdbuf());cout.rdbuf(outFile.rdbuf()); //原程式碼int n;while (cin>>n){n *= 2;cout<<n<<endl;}inFile.close();outFile.close();//回到控制台的標準輸入輸出cin.rdbuf(strmin_buf);cout.rdbuf(strmout_buf);cout<<"檔案已經處理完畢 輸入0表示結束:"<<endl;do{cin>>n;}while (n != 0);return 0;}
運行結果如所示:
同樣,這個程式也完成了輸入輸出的重新導向。
上面的方法都是建立在修改原始碼的基礎上,如果只有程式檔案即.exe檔案那應該怎麼做了?請參閱下一篇《進程通訊之二 管道技術第二篇 匿名管道》
轉載請標明出處,原文地址:http://blog.csdn.net/morewindows/article/details/7390350
如果覺得本文對您有協助,請點擊‘頂’支援一下,您的支援是我寫作最大的動力,謝謝。