创建进程,调用Rscript运行相关算法[基于本公司的底层,可以修改,完全去掉依赖这个底层]

来源:互联网 发布:手机淘宝怎么投诉盗图 编辑:程序博客网 时间:2024/06/05 16:04

#include "ARIMA_R.h"
#include "BSDCoreLibrary.h"
using namespace bsd;
BSDLogger* pbsdlog = getBSDSysLogger();
BSDLogger& bsdlog = *pbsdlog;


bool ARIMA_R::AnayParam() {
AnaWord aw;
bsdlog.info("解析输入输出参数!");
aw.Import(m_strParameter);
//if (AnaSyntax::exist("/XDATA", aw))
//{
// AnaSyntax::getVAR("/XDATA", aw, m_aryFeildName);
//} else 
//{
// bsdlog.error("变量字段名输入不正确!");
// return false;
//}
// intperiod;
// bool includemean;
if(AnaSyntax::exist("/CSV",aw))
{
csvpath=AnaSyntax::getSingleStr("/CSV",aw);
}
else
{
bsdlog.error("无数据源!");
return false;

if(AnaSyntax::exist("/NONAME",aw))
{
hasnoname=false;
}
if(AnaSyntax::exist("/ZHIBIAOFU",aw))
{
m_sepator="\" \"";
}
if(AnaSyntax::exist("/KONGGE",aw))
{
m_sepator="\" \"";
}
if(AnaSyntax::exist("/DOUHAO",aw))
{
m_sepator="\",\"";
}
if(AnaSyntax::exist("/FENHAO",aw))
{
m_sepator="\";\"";
}
if(AnaSyntax::exist("/MODEL",aw))
{
m_ar=AnaSyntax::getvalue("/MODEL","AR",aw);
m_df=AnaSyntax::getvalue("/MODEL","DF",aw);
m_ma=AnaSyntax::getvalue("/MODEL","MA",aw);
}


if(m_ar<0||m_df<0||m_ma<0)
{
bsdlog.error("order参数必须大于等于0的");
return false;
}
if(AnaSyntax::exist("/SEASONAL",aw))
{
m_period=AnaSyntax::getvalue("/SEASONAL","PERIOD",aw);
}
else
{
m_periodNA="NA";
}
if (AnaSyntax::findstr("/INCLUDE", "FALSE", aw)) 
{
m_includemean = false;
}
if (AnaSyntax::findstr("/TRANSFORM", "FALSE", aw)) 
{
m_transformpars = false;
}
if (AnaSyntax::findstr("/METHOD", "CSS-ML",aw))                          
m_nMethod = 0;//全部选入[默认]
else if (AnaSyntax::findstr("/METHOD", "ML",aw))                 
m_nMethod = 1;
else if(AnaSyntax::findstr("/METHOD","CSS",aw))                 
m_nMethod = 2;
return true;
}
ARIMA_R::ARIMA_R() {
m_periodNA="";
m_includemean=true;
m_transformpars=true;
m_nMethod=0;
hasnoname=true;
m_sepator=",";
}
ARIMA_R::~ARIMA_R() {


}
#include <fstream>
bool ARIMA_R::CreateProcess_R(string csvpath,double AR,double DF,double MA)
{
STARTUPINFO startupinfo;
ZeroMemory(&startupinfo,sizeof(STARTUPINFO));
startupinfo.cb=sizeof(STARTUPINFO);
startupinfo.wShowWindow=SW_HIDE;
startupinfo.dwFlags=STARTF_USESHOWWINDOW;
PROCESS_INFORMATION process_info;
string r_Cmdpath="D:\\Program Files\\R\\R-3.0.0\\bin\\Rscript "; //绝对路径 R  //TODO
// string csvpath="D:/adl_arima.csv";
string strr="\\",str_t="/";
int pos=csvpath.find(strr);////查找指定的串
while (pos != -1)
{
csvpath.replace(pos,strr.length(),str_t);////用新的串替换掉指定的串
pos = csvpath.find(strr);//////继续查找指定的串,直到所有的都找到为止
}
fstream rSourceFile("RsourceFile.R",ios::in|ios::out|ios::trunc);
// rSourceFile<<"x<-read.csv(\""+csvpath+"\")"<<endl;
if(hasnoname)
rSourceFile<<"x<-read.csv(\""+csvpath+"\""+",TRUE,"+m_sepator+")"<<endl;
else
rSourceFile<<"x<-read.csv(\""+csvpath+"\""+"FALSE"+m_sepator+")"<<endl;
rSourceFile<<"arima(x";
//double ar转为string
string ar_string;
stringstream ar_ss;
ar_ss<<m_ar;
ar_ss>>ar_string;


//double df转为string
string df_string;
stringstream df_ss;
df_ss<<m_df;
df_ss>>df_string;


//double ma转为string
string ma_string;
stringstream ma_ss;
ma_ss<<m_ma;
ma_ss>>ma_string;


rSourceFile<<",c("+ar_string+","+df_string+","+ma_string+")"<<endl;
if(m_periodNA.compare("NA")==0)
rSourceFile<<",seasonal=list(order=c("+ar_string+","+df_string+","+ma_string+"),"+"NA)"<<endl;
else
{
//double ma转为string
string period_string;
stringstream period_ss;
period_ss<<m_period;
period_ss>>period_string;
rSourceFile<<",seasonal=list(order=c("+ar_string+","+df_string+","+ma_string+"),"+period_string+")"<<endl;
}
rSourceFile<<",xreg = NULL";
if(m_includemean)
rSourceFile<<",include.mean=TRUE"<<endl;
else
rSourceFile<<",include.mean=FALSE"<<endl;
if(m_transformpars)
rSourceFile<<",transform.pars = TRUE";
else
rSourceFile<<",transform.pars = FALSE";
rSourceFile<<",fixed = NULL, init = NULL";
if(m_nMethod==0)
rSourceFile<<",method = c(\"CSS-ML\")";
if(m_nMethod==1)
rSourceFile<<",method = c(\"ML\")";
if(m_nMethod==2)
rSourceFile<<",method = c(\"CSS\")";
rSourceFile<<")";
rSourceFile.close();
string cmd_all=r_Cmdpath+"RsourceFile.R"+" >result.txt";
::CreateProcess(NULL,(LPSTR)cmd_all.c_str(),NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS ,NULL,NULL,&startupinfo,&process_info);
::CloseHandle(process_info.hThread);
::CloseHandle(process_info.hProcess);


return true;


}
bool ARIMA_R::AddResult()
{
//写入result集中
RsltElementTextPtr RText;
RText.setName("ARIMA输出结果");
string result_string;
fstream file("result.txt",ios::in|ios::out);
while (!file.fail())  
{
getline ( file, result_string); 
string strr=" ",str_t="&nbsp";
int pos=result_string.find(strr);////查找指定的串
while (pos != -1)
{
result_string.replace(pos,strr.length(),str_t);////用新的串替换掉指定的串
pos = result_string.find(strr);//////继续查找指定的串,直到所有的都找到为止
}
if(result_string.compare("Call:")==0)
RText.addString("输入参数情况<br>");
else
RText.addString(result_string+"<br>");
}
m_pResult->add(RText);
file.close();
return true;
}
bool ARIMA_R::RunArithmetic(Result& result) {
m_pResult = &result;
if(!AnayParam())                        //读取输入参数
return false;
CreateProcess_R(csvpath,m_ar,m_df,m_ma);//调用R进程
AddResult();
return true;
}

代码是基于本公司的相关底层库,除了解析字符串过程,其他和底层无关。主要分析调用进程的问题::CreateProcess的部分各参数说明,调用R语言的Rscript.exe来运行R代码


startupinfo.wShowWindow=SW_HIDE;
startupinfo.dwFlags=STARTF_USESHOWWINDOW;  //隐藏弹出的cmd窗口


原型:
BOOL CreateProcess(
LPCSTR lpApplicationName, 
//可执行文件的名称
LPSTR lpCommandLine, 
//指定了要传递给执行模块的参数
NULL,
//进程安全性,设为 NULL 表示使用默认安全属性LPSECURITY_ATTRIBUTES lpProcessAttributes,
//线程安全性,设为 NULL 表示使用默认安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes
//指定当前进程的可继承句柄是否可以被新进程继承
BOOL bInheritHandle,
//指定了新进程的优先级和其它创建标志
DWORD dwCreationFlags,
LPVOID lpEnvironment,
//指定了新进程使用的环境变量
LPCSTR lpCurrenDirectory,
//新进程使用的目录
LPSTARUPINFO lpStartupinfo, 
//指定新进程的显示信息
//返回新建进程的标志信息,ID ,句柄等
LPPROCESS_INFORMATION lpProcessInformation
)
 
上面的参数的数据类型是 Windows 自定义的数据类型,具体定义在 WINDEF.h文件中,下面列出一部分常用的数据类型
typedef unsigned long   DWORD;
typedef int           BOOL;
typedef unsigned char   BYTE;
typedef unsigned short WORD
typedef float          FLOAT;
typedef void far      *LPVOID;
typedef int           INT;
typedef unsigned int    UINT;
 
lpProcessInformation 参数是一个指向 PROCESS_INFORMATION 结构的指针,CreateProcess 函数返回之前会初始化这些结构成员,结构定义如下:
typedef struct
{
       HANDLE hProcess;   //新建进程的内核句柄
       HANDLE hThread;   //新建进程中主线程的内核句柄
       DWORD dwProcessId;   //新建进程的ID 
       DOWRD dwThreaId;    //新建进程的主线程ID 
}
 
 
创建进程以后,必须调用 CloseHandle 函数关闭所创建的进程内核对象和线程内核对象,否则进程虽然终止了,但是该进程占用的资源依然没有释放
 
完整示例代码如下(该程序运行的时候会自动打开系统自带的记事本程序):
 
#include <windows.h>
 
 
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    char *szCommandLine = "notepad.exe";
    STARTUPINFO si = {sizeof(si)}; //初始化STARTUPINFO 结构的大小
    PROCESS_INFORMATION pi; //该变量保存新建进程的标志信息
    BOOL bRet = ::CreateProcess(NULL, //不在此指定可执行的文件名
                                szCommandLine, //命令行参数
                                NULL, //默认进程安全属性
                                NULL, //默认线程安全属性
                                FALSE, //指定当前进程内的句柄不可以被新进程继承
                                NULL,   //使用默认的创建方式
                                NULL,   //使用本进程的环境变量
                                NULL,   //使用本进程的目录
                                &si,    //使用默认的显示方式
                                &pi); //保存新建进程的标志信息
    if(bRet)
    {
        //关闭新建进程和主线程的句柄
        ::CloseHandle(pi.hProcess);
        ::CloseHandle(pi.hThread);
    }
    return 0;
}