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

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("文件错误");
        }
发布了4 篇原创文章 · 获赞 1 · 访问量 6646
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览