在C#中調用命令執行R腳本,要實現這個功能我們得知道:(1)如何用c#調用系統命令;(2)如何用系統命令執行R腳本;(3)如何寫R腳本
一、C#調用系統命令
這里的“startInfo.FileName = "cmd.exe";”是通過C#調用的系統命令,當然你也可以執行cmd.exe,也可以執行其他的應用和程序,比如計算器“calc”,R程序“R.exe”等。這里的“string[] command”參數是要執行的命令語句,我這里是針對的是控制台,因為其他的應用程序我不知道怎么將參數傳入程序中。

1 /// <summary> 2 /// 執行DOS命令,返回DOS命令的輸出 3 /// </summary> 4 /// <param name="dosCommand">dos命令</param> 5 /// <param name="milliseconds">等待命令執行的時間(單位:毫秒), 6 /// 如果設定為0,則無限等待</param> 7 /// <returns>返回DOS命令的輸出</returns> 8 public string Execute(string[] command, int seconds = 10) 9 { 10 string output = ""; //輸出字符串 11 if (command[0] != null && !command[0].Equals("")) 12 { 13 Process process = new Process();//創建進程對象 14 ProcessStartInfo startInfo = new ProcessStartInfo(); 15 startInfo.FileName = "cmd.exe";//設定需要執行的命令 16 //startInfo.Arguments = "/C " + command;//“/C”表示執行完命令后馬上退出 17 //startInfo.Arguments = command;//“/C”表示執行完命令后馬上退出 18 startInfo.UseShellExecute = false;//不使用系統外殼程序啟動 19 startInfo.RedirectStandardInput = true; //重定向輸入 20 startInfo.RedirectStandardOutput = true; //重定向輸出 21 startInfo.CreateNoWindow = true;//不創建窗口 22 process.StartInfo = startInfo; 23 try 24 { 25 if (process.Start())//開始進程 26 { 27 if (seconds == 0) 28 { 29 process.WaitForExit();//這里無限等待進程結束 30 } 31 else 32 { 33 process.WaitForExit(seconds); //等待進程結束,等待時間為指定的毫秒 34 } 35 StreamWriter sw = process.StandardInput; 36 sw.WriteLine(command[0]); 37 sw.WriteLine(command[1]); 38 sw.Close(); 39 //process.StandardInput.Close(); 40 output = process.StandardOutput.ReadToEnd();//讀取進程的輸出 41 } 42 } 43 catch 44 { 45 } 46 finally 47 { 48 if (process != null) 49 process.Close(); 50 } 51 } 52 return output; 53 }
二、 用系統命令執行R腳本
先說明一下用控制台執行R腳本,而之后的用C#調用系統命令執行R腳本就是將這些控制台的語句當作參數傳入上面的string[] command數組中
1、將R.exe所在路徑加到環境變量path下,路徑一般為C:\Program Files\R\R-3.0.1\bin或者在控制台中敲入要轉入的目錄。
2、在windows 命令行中敲入 調用命令:r CMD BATCH D:\RWORKSPACE\CMD_TEST.R (注意 CMD BATCH 都要大寫)
命令的普遍形式為R CMD command file,command是別的工具。比如前面用到的批處理工具BATCH。
這樣它就在執行R腳本了。我的測試腳本很簡單,當然你可以寫的很復雜,執行你要完成的任務。
結果它會生成一個rasterName.csv的結果文件和執行狀態的文件Test.r.Rout文件
三、 寫R腳本
當然你可以很簡單的在記事本中寫R腳本,但是為了應用程序的可交互性,你可以用代碼在記事本中寫腳本,但是要注意的是文件路徑的問題。因為在R程序中的路徑是“\\”或者“/”的,你的代碼中可以將獲取的路徑的符號其替換為“\\\\”或者“/”。不然無法讀取文件。

1 /// <summary> 2 /// 創建隨機森林影像分類R腳本 3 /// </summary> 4 /// <param name="rowCount"></param> 5 /// <param name="columnCount"></param> 6 /// <param name="bandCount"></param> 7 /// <param name="workPath"></param> 8 /// <param name="roiPath"></param> 9 /// <param name="rasterPath"></param> 10 public void CreateRandomForestScript(int rowCount=2850, int columnCount=2850, int bandCount=4, string workPath = @"D:", string roiPath = "", string rasterPath = "") 11 { 12 string scriptPath = System.IO.Path.GetFullPath(workPath) + @"\randomForest.r"; 13 workPath = workPath.Replace("\\", "\\\\"); //workPath = workPath.Replace('\\', '/'); 14 roiPath = roiPath.Replace("\\", "\\\\"); 15 rasterPath = rasterPath.Replace("\\", "\\\\"); 16 string resultName = "rasterResult.txt"; 17 string str = ""; 18 string funStr = ""; 19 using (StreamWriter sr = new StreamWriter(scriptPath,false,Encoding.GetEncoding("GB2312"))) 20 { 21 str = "setwd('"+workPath+"')\n"; 22 str += "library(randomForest)\n"; 23 str += "roi<-read.table('" + roiPath + "')\n"; 24 //str += "roi<-read.table(file.choose())\n"; 25 str += "raster<-read.table('" + rasterPath + "')\n"; 26 //str += "raster<-read.table(file.choose())\n"; 27 funStr = "V" + (bandCount + 1) + "~"; 28 for (int i = 0; i < bandCount;i++) 29 { 30 funStr += "V" + (i + 1)+"+"; 31 } 32 funStr = funStr.Remove(funStr.Length-1); 33 str += "spam<-randomForest("+funStr+",data=roi)\n"; 34 //str += "spam<-randomForest(V5~V1+V2+V3+V4,data=roi)\n"; 35 str += "rm(roi)\n"; 36 str += "gc()\n"; 37 str += "c<-predict(spam,raster,type='response')\n"; 38 str += "rm(spam)\n"; 39 str += "rm(raster)\n"; 40 str += "gc()\n"; 41 str += "e<-unlist(c)\n"; 42 str += "result<-matrix(e,nrow="+rowCount+",ncol="+columnCount+")\n"; 43 str += "rm(c)\n"; 44 str += "rm(e)\n"; 45 str += "gc()\n"; 46 str += "write.table(result, '" + resultName + "')\n"; 47 str += "rm(result)\n"; 48 str += "gc()\n"; 49 sr.WriteLine(str); 50 sr.Close(); 51 } 52 }
這是寫的創建隨機森林影像分類的腳本的函數,產生的腳本文件如下:
四、 調用系統命令執行R腳本
主要的是command 參數那兩行代碼

1 private void buttonOK_Click(object sender, EventArgs e) 2 { 3 try 4 { 5 if (workPath == "" || roiPath == "" || rasterPath == "" || textBoxX1.Text == "" || textBoxX2.Text == "") 6 return; 7 rowCount = Convert.ToInt32(textBoxX1.Text); 8 columnCount = Convert.ToInt32(textBoxX2.Text); 9 bandCount = Convert.ToInt32(integerInput1.Value); 10 RandomForestClassfier randomForest = new RandomForestClassfier(); 11 randomForest.CreateRandomForestScript(rowCount, columnCount, bandCount, workPath, roiPath, rasterPath); 12 string[] command = new string[2]; 13 command[0] = "cd /d C:\\Program Files\\R\\R-3.2.1\\bin\\x64"; 14 command[1] = "r CMD BATCH "+workPath+@"\randomForest.r"; 15 randomForest.RunRandomForestScript(command); 16 MessageBox.Show("影像分類完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 17 } 18 catch (Exception ex) 19 { 20 MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 21 } 22 }
五、 參考資料
1.http://www.jb51.net/article/57477.htm
2.http://www.jb51.net/article/26993.htm
3.http://q.cnblogs.com/q/44086/
4.http://blog.csdn.net/diyiziran/article/details/21379181
5.http://book.2cto.com/201305/21969.html