想做一个能够在线编译代码运行的平台,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. matlab矩阵与数组

    数组运算:数与数组加减:k+/-A %k加或减A的每个元素数组乘数组: A.*B %对应元素相乘数组乘方: A.^k %A的每个元素k次方:k.^A,分别以k为底A的各元素为指数求幂值数除以数组: k ...

  2. 置换群(本蒟蒻瞎BB的)(未完)

    置换群(本蒟蒻瞎BB的)(未完) 群的定义 给定一个集合\(G=\{a, b, c...\}\)和集合\(G\)上的二元运算*,并满足: 封闭性:\(\forall a, b \in G, \exis ...

  3. Java:基本语法

    Java语言是由类和对象组成的,其对象和类又是由变量和方法组成,而方法,又包含了语句和表达式. 1. 变量 Java语言提供了两种变量:成员变量和局部变量 成员变量:是在方法体外的类中声明和定义的,可 ...

  4. Git 通过https向码云推送项目

  5. Proxy opening connection toSpringClound配置豪猪hystrixDashboard发生

    Proxy opening connection to: http://localhost:8001/hystrix.stream 配置hystrixDashboard发生的错误.一直在寻找 最后发现 ...

  6. JS——json、ajax、jsonp

    json: data.json: { "code":1, "data": { "name": "kid", " ...

  7. Vue源码学习之数据初始化

    首发地址:CJWbiu's Blog 在这里思考一个问题,使用Vue的时候需要在创建Vue实例时传入一个option,这里包含了我们定义的props.methods.data等.而在methods的方 ...

  8. kettle5.4ODBC和OCI连接配置

    1.kettle 5.4 使用JDBC连接的时候报错(测试不同的数据库,发现只是连接11gRAC 的时候会报JDBC的错误) 具体报错如下 java.sql.SQLException: 建数据库连接出 ...

  9. Linux安装配置相关

    1.常用汇总 useradd usertemp //添加用户 passwd usertemp //修改/设置密码 userdel usertemp //删除用户 2. profile/baserc等配 ...

  10. Java排序算法(三)

    Java排序算法(三) 三.Java排序算法总结 从这三组时间复杂度对比中,可以看出,堆排序和归并排序是不管在什么情况下发挥稳定的,快速排序好的时候表现如天才,坏情况下比较差强人意,甚至在等待排序个数 ...