想做一个能够在线编译代码运行的平台,Java和SQL已经支持了,因为是用Java写的后台,所以Java和SQL挺容易就实现了,做到支持C的时候就卡住了,网上搜了一下这种帖子好像很少。

我采取的办法是就是刚开始学C语言的教的调用GCC来编译.C文件的文件,首先将前端传过来的C代码写入到特定的路径下,然后利用Java的API调用CMD来执行gcc命令编译这个文件,这好像有点MakeFile文件的意思。。编译之后继续调用CMD执行生成的exe,同时获取CMD的输出,至此整个过程完成,但是最后需要做好一项善后工作,那就是继续调用CMD将这个exe的进程杀掉,否则会出现问题,因为exe还没停止,继续编译写入会报权限问题。

封装了整个编译运行的Servivce:

package com.mine.ide.service.implement;

import com.mine.ide.util.CLangUtil;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service; import java.io.*;
import java.util.concurrent.*; /**
* @author yintianhao
* @createTime 20190625 11:14
* @description ExecuteCLang
*/
@Service
public class ExecuteCLangService {
private static final Logger log = Logger.getLogger(ExecuteCLangService.class); //代码存放路径
public static final String CODE_PATH = "D:\\springboot2\\code\\"; /**
* @param content C代码
* */
private boolean generateCFile(String content){
BufferedWriter out = null;
try{
//写入
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(CODE_PATH+"test.c", false)));
out.write(content);
}catch (Exception e){
log.error(e.getCause().getMessage());
return false;
}finally {
try {
out.close();
}catch (IOException e){
log.error(e.getCause().getMessage());
return false;
}
}
return true;
}
/**
* @param sourceCode 源代码
* */
public String runCLangCode(String sourceCode){
//先生成文件
generateCFile(sourceCode);
Executor executor = Executors.newSingleThreadExecutor();
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
//编译C文件
String compileResult = execCmd("gcc -o "+CODE_PATH+"test "+CODE_PATH+"test.c",null);
if (compileResult.equals(""))
//编译不出错的情况,replaceAll将\n换成HTML的换行,空格换成HTML的空格
return execCmd(CODE_PATH+"test.exe",null).replaceAll("\n","<br/>").replaceAll(" ","&nbsp;");
else {
//编译出错,找到error的位置,返回error及其后的信息
int errorIndex = compileResult.indexOf("error");
return compileResult.substring(errorIndex).replaceAll("\n","<br/>").replaceAll(" ","&nbsp;");
}
}
});
executor.execute(futureTask);
try {
//编译运行完毕将text.exe的进程kill
execCmd("taskkill /f /im test.exe",null);
log.info("killed test.exe");
}catch (Exception e){
e.printStackTrace();
}
String result = "";
try{
//设置超时时间
result=futureTask.get(10, TimeUnit.SECONDS);
}catch (InterruptedException e) {
log.info("Interrupt");
result = "程序中断,请检查是否有内存冲突等错误";
// future.cancel(true);
}catch (ExecutionException e) {
result = "程序执行错误";
futureTask.cancel(true);
}catch (TimeoutException e) {
result = "时间超限,请检查是否存在无限循环等程序无法自动结束的情况";
}
log.info("result - "+result);
return result.equals("")?"没有输出":result;
}
/**
* 执行系统命令, 返回执行结果
* @param cmd 需要执行的命令
* @param dir 执行命令的子进程的工作目录, null 表示和当前主进程工作目录相同
*/
private String execCmd(String cmd, File dir) throws Exception {
StringBuilder result = new StringBuilder(); Process process = null;
BufferedReader bufrIn = null;
BufferedReader bufrError = null; try {
// 执行命令, 返回一个子进程对象(命令在子进程中执行)
process = Runtime.getRuntime().exec(cmd, null, dir); // 方法阻塞, 等待命令执行完成(成功会返回0)
process.waitFor(); // 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出(PS: 子进程的输出就是主进程的输入)
bufrIn = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
bufrError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); // 读取输出
String line = null;
while ((line = bufrIn.readLine()) != null) {
result.append(line).append('\n');
}
while ((line = bufrError.readLine()) != null) {
result.append(line).append('\n');
} } finally {
closeStream(bufrIn);
closeStream(bufrError); // 销毁子进程
if (process != null) {
process.destroy();
}
} // 返回执行结果
return result.toString();
} private void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
// nothing
}
}
}
}

至此写完,之后只要调用runCLangCode方法就可以了

Java后台调用gcc编译C语言代码的更多相关文章

  1. 在Linux使用GCC编译C语言共享库

    在Linux使用GCC编译C语言共享库 对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例 ...

  2. gcc编译c语言程序

    编译:当前源代码编译成二进制目标文件(.obj文件) 链接(link):将生成的.obj文件与库文件.lib等文件链接,生成可执行文件(.exe文件).   一个现代编译器的主要工作流程如下: 源程序 ...

  3. 在Ubuntu 16.04 LTS上用g++和gcc编译C/C++代码错误提示“.../x86_64-linux-gnu/crt1.o: ELF section name out of range”

    (有一些图片我是直接从个人的CSDN博客上复制来的) 最近一个多月来,我曾经多次尝试在Ubuntu 16.04 LTS上使用g++和gcc(这俩好像合起来叫MinGW?)来编译C/C++代码,但是在解 ...

  4. linux 编译C语言代码后产生OBJ文件的方法

    如果你不指定编译成什么文件,gcc默认一步到位,直接生成可执行文件你可以试试以下几个参数 -c 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 例子用法: gcc -c hello.c 他 ...

  5. 用gcc编译c语言程序以及其编译过程

    对于初学c语言编程的我们来说,学会如何使用gcc编译器工具,对理解c语言的执行过程,加深对c语言的理解很重要!!! 1.预编译 --> 2.编译 --> 3.汇编 --> 4.链接- ...

  6. 在 Linux 使用 GCC 编译C语言共享库

    对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例如一个数据库服务器的接口,就像MySQL ...

  7. java后台调用HttpURLConnection类模拟浏览器请求(一般用于接口调用)

    项目开发中难免遇到外部接口的调用,小生今天初次接触该类,跟着API方法走了一遍,如有不对的地方,还请哆哆指正,拜谢! 1 package com.cplatform.movie.back.test; ...

  8. java后台调用http请求

    1:代码   @Value("${sms.username}")  可以将sms.properties配置文件中的值注入到username //这种方式是将sms.properti ...

  9. md5签名加密(用于java 后台调用短信平台接口实现发短信)

    MD5Util 方法 package com.funcanteen.business.action.pay.util; import java.security.MessageDigest; publ ...

随机推荐

  1. 图解Linux安装jdk

    测试是否安装成功: 查看Java的版本命令:java -version Windows:查看java版本的方法是:运行--->cmd,输入java –version.注意: linux:终端中输 ...

  2. Webpack打包时警告 - Critical dependency: the request of a dependency is an expression

    关于解决 [Webpack] Critical dependency: the request of a dependency is an expression ------------------- ...

  3. python绘制世界人口地图

    最近看了<python编程:从入门到实践>,里边设计的项目拿来学习学习,绘制世界人口地图. 首先,下载数据,http://data.okfn.org/ ,从这里下载population_d ...

  4. myeclipse svn 在线安装

    https://www.cnblogs.com/sxdcgaq8080/p/6000446.html http://subclipse.tigris.org/update_1.8.x

  5. win下rabbitmq的安装

    安装erlang 10.4 和 rabbitmq 3.7.5 然后关闭rabbitmq服务 然后设置 erlang和rabbitmq的环境变量 ERLANG_HOME=erlang安装目录 RABBI ...

  6. (二)异步解决方案之callback

    回调定义 就是一个函数里面使用 作为参数的函数. Function1(Function2) { Function2(); }; 同步调用 - 老实说,这和我们 不将代码封装成 函数没有差别 也就是说 ...

  7. js——bootstrap框架

    前端开发框架,移动优先,响应式布局开发. 网址:www.bootcss.com js有一个特性是阻塞加载,也就是说js文件如果没有加载完,不会进行后面的加载,所以例子中会把js文件写在body的最后一 ...

  8. Nodejs mysql pool使用实例

    前段时间在写一个版本发布工具,用到express+mysql实现,当站点运行很长一段空白时间后,node进程会自动down掉,提示mysql连接错误,谷歌后发现是mysql自身的特性导致,因此后来改为 ...

  9. logAB = logA + logB; A,B>0

    令 X = logA, Y = logB, Z=logAB .2x = A, 2y = B, 2z = AB, 则有 2z = AB = 2x * 2y = 2x+y ,有z = x+y,即 logA ...

  10. koa2 从入门到进阶之路 (四)

    之前的文章我们介绍了一下 koa 中间件 以及 koa 中间件的洋葱图执行流程,本篇文章我们来看一下 koa 中使用 ejs 模板及页面渲染. 在 Express 中,我们经常会用 ejs 模板来渲染 ...