用C#调用R语言开发.NET MVC Web服务

来源:互联网 发布:矩阵怎么输 matlab 编辑:程序博客网 时间:2024/05/25 19:55

R语言是个解释执行的语言,语法风格对于常年写C#的我来说非常怪异。并且R的web包shiny用起来也不是很顺手,所以如果要把R的功能用作生产,我倾向于用高级语言给他做一次封装,这样无论是可扩展性还是性能调优空间都会比较有把握。

用.NET调用R语言的方法有两种,一是采用R.net库,官方地址:R.NET,另外一种是利用控制台执行.R代码。我采用的是第二种方法,为什么倾向于第二种后面会说,先简单介绍一下两种不同的方法。

R.NET

R.net可以在C#代码里开启一个R引擎,然后往R引擎中塞入代码段或者直接执行.R文件,并获取执行结果,他的代码大概长这样子

static void Main(string[] args){    REngine.SetEnvironmentVariables(); // <-- May be omitted; the next line would call it.    REngine engine = REngine.GetInstance();    // A somewhat contrived but customary Hello World:    CharacterVector charVec = engine.CreateCharacterVector(new[] { "Hello, R world!, .NET speaking" });    engine.SetSymbol("greetings", charVec);    engine.Evaluate("str(greetings)"); // print out in the console    string[] a = engine.Evaluate("'Hi there .NET, from the R engine'").AsCharacter().ToArray();    Console.WriteLine("R answered: '{0}'", a[0]);    Console.WriteLine("Press any key to exit the program");    Console.ReadKey();    engine.Dispose();}

但显然这种方法有三个弊端:

  • 不适合R代码已经开发好的情况
  • 会花费一些没有太大意义的学习成本去熟悉这个库的规则
  • 无法保证这个R.NET的版本能跟上R的版本更新

.NET启动控制台调用R代码

所以我个人倾向于用控制台去调用.R的代码,通过文件IO进行输入输出。流程图如下

Created with Raphaël 2.1.0.NET.NETRR生成sessionIdinput_sessionId.csv文件output_sessionId.csv文件解析csv文件并返回数据

sessionId为在调用开始的时候生成的一个唯一的guid,通过这个guid让各个进程读取自己的input/output文件,保证在多线程环境下互不干扰

关键代码如下

        // input文件通过post上传        public ActionResult Upload(HttpPostedFileBase file)        {            var sessionId = Guid.NewGuid().ToString("N");            var rPath = Server.MapPath("~/RConsole/");//.R代码的位置            if (file != null)            {                //保存input文件                file.SaveAs(rPath + "input_" + sessionId + ".csv");                //启动R                Process cmd = new Process();                //R的安装目录                cmd.StartInfo.FileName = @"C:\Program Files\R\R-3.3.1\bin\Rscript.exe";                cmd.StartInfo.WorkingDirectory = rPath;                cmd.StartInfo.UseShellExecute = false;                    cmd.StartInfo.RedirectStandardOutput = true;/                cmd.StartInfo.RedirectStandardError = true;                cmd.StartInfo.Arguments = " Evaluator.r " + sessionId;                cmd.StartInfo.CreateNoWindow = true;//不显示程序窗口                cmd.Start();//启动程序                var output = cmd.StandardOutput.ReadToEnd();                var error = cmd.StandardError.ReadToEnd();                cmd.WaitForExit();//等待控制台程序执行完成                cmd.Close();//关闭该进程                var outputFilePath = rPath + "output_" + sessionId + ".csv";                //读取output文件                var csv = new CsvReader(new StreamReader(outputFilePath));                return Json(csv.GetRecords<Result>().ToList());            }            return Content("文件错误");        }
0 0
原创粉丝点击