进程间通信二:管道技术之输入输出重定向
转载自:http://blog.csdn.net/morewindows/article/details/7390350
本篇将介绍输入输出的重定向问题,先来看一个小小的实例,设有一个程序,该程序的输入输出为标准输入输出即从键盘上输入,输出到屏幕。现在要重定向输入法输出,使程序从文件中读取数据,处理后输出到文件。程序代码如下(称此程序为示例程序):
- #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;
- }
运行结果如下图所示:
同样,这个程序也完成了输入输出的重定向。