现在的位置: 首页 > 综合 > 正文

进程通信之二 管道技术第一篇 输入输出的重定向

2013年08月01日 ⁄ 综合 ⁄ 共 3441字 ⁄ 字号 评论关闭

继上一篇《进程通信之一使用WM_COPYDATA C++C#实现》,进程通信之二将分为三篇文章讲解如何使用管道技术来完成进程通信功能。三篇文章目录如下:

1进程通信之二 管道技术第一篇 输入输出的重定向

2进程通信之二 管道技术第二篇 匿名管道

3进程通信之二 管道技术第三篇 命名管道

 

本篇将介绍输入输出的重定向问题,先来看一个小小的实例,设有一个程序,该程序的输入输出为标准输入输出即从键盘上输入,输出到屏幕。现在要重定向输入法输出,使程序从文件中读取数据,处理后输出到文件。程序代码如下(称此程序为示例程序):

#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++中就有ifstreamofstream这二个类来帮助我们完成这一任务。这个二类的详细功能就不细说了。下面介绍下如何使用这二个类来重定向程序的输入输出(看的时候看慢点喔,不会会被很多类名给搞晕去^_^)。

 

这二个类可以以读的方式和写的方法打开一个文件(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++中大家平常使用的cincout,可以在iostream文件中找到cincout的定义,这二个实际是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;

 

明显cincoutifstream类和ofstream类有着非常密切关系——cinbasic_istream类的变量,而ifstream则是basic_istream类的派生类。coutbasic_ostream类的变量,而ofstream则是basic_ostream类的派生类。

 

有了这个后,猜测很可能会有某个成员函数能将它们联系到一起,从而让cin和cout由标准输入输出重定向到从文件中读取,输出到文件。事实上basic_istream类实际是虚继承于basic_ioso类,basic_ostream类实际是虚继承于basic_ios类。这二个类都有个rdbuf()成员函数,这个函数允许我们访问和修改类中一个类型为basic_streambuf类的成员变量。改动这个变量就能重定向输入输出。因此对cin和cout调用这个rdbuf()函数并传入ifstreamofstreamrdbuf()就可以将控制台的标准输入输出改成从文件中读取和输出到文件。

 

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

如果觉得本文对您有帮助,请点击支持一下,您的支持是我写作最大的动力,谢谢。

 

抱歉!评论已关闭.