Java后台调用gcc编译C语言代码
想做一个能够在线编译代码运行的平台,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(" "," ");
else {
//编译出错,找到error的位置,返回error及其后的信息
int errorIndex = compileResult.indexOf("error");
return compileResult.substring(errorIndex).replaceAll("\n","<br/>").replaceAll(" "," ");
}
}
});
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语言代码的更多相关文章
- 在Linux使用GCC编译C语言共享库
在Linux使用GCC编译C语言共享库 对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例 ...
- gcc编译c语言程序
编译:当前源代码编译成二进制目标文件(.obj文件) 链接(link):将生成的.obj文件与库文件.lib等文件链接,生成可执行文件(.exe文件). 一个现代编译器的主要工作流程如下: 源程序 ...
- 在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++代码,但是在解 ...
- linux 编译C语言代码后产生OBJ文件的方法
如果你不指定编译成什么文件,gcc默认一步到位,直接生成可执行文件你可以试试以下几个参数 -c 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 例子用法: gcc -c hello.c 他 ...
- 用gcc编译c语言程序以及其编译过程
对于初学c语言编程的我们来说,学会如何使用gcc编译器工具,对理解c语言的执行过程,加深对c语言的理解很重要!!! 1.预编译 --> 2.编译 --> 3.汇编 --> 4.链接- ...
- 在 Linux 使用 GCC 编译C语言共享库
对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例如一个数据库服务器的接口,就像MySQL ...
- java后台调用HttpURLConnection类模拟浏览器请求(一般用于接口调用)
项目开发中难免遇到外部接口的调用,小生今天初次接触该类,跟着API方法走了一遍,如有不对的地方,还请哆哆指正,拜谢! 1 package com.cplatform.movie.back.test; ...
- java后台调用http请求
1:代码 @Value("${sms.username}") 可以将sms.properties配置文件中的值注入到username //这种方式是将sms.properti ...
- md5签名加密(用于java 后台调用短信平台接口实现发短信)
MD5Util 方法 package com.funcanteen.business.action.pay.util; import java.security.MessageDigest; publ ...
随机推荐
- Mybatis中文模糊查询,数据库中有数据,但无结果匹配
1.Mybatis中文模糊查询,数据库中有数据,但无结果匹配 1.1 问题描述: Mybatis采用中文关键字进行模糊查询,sql语句配置无误,数据库有该数据,且无任何报错信息,但无查询结果 1.2 ...
- Cogs 6. 线型网络
6. 线型网络 ★★☆ 输入文件:linec.in 输出文件:linec.out 简单对比时间限制:1 s 内存限制:256 MB [问题描述] 有 N(N<=20)台 PC 放 ...
- Java学习笔记——Map接口
Map接口 Map接口 Map接口中键和值一一映射. 可以通过键来获取值. 异常 NoSuchElementException:访问的值不存在 ClassCastException:对象类型错误 Un ...
- 帝都Day7——解放篇
昨天晚上的problems: songfen 坠大子段和,要把[l,r]其中一个数变成P,我们要把最小的数变成p. 当L,R没有取满整个区间,P可以在[L,R]外面!!!!!!!这种情况真是令人绝望. ...
- CPU死锁
https://blog.csdn.net/sunny05296/article/details/82858071 最近碰到了Centos7.2上终端打印soft lockup CPU死锁,系统无响应 ...
- PHPExcel探索之旅---阶段一
类似于Java,php也有操作Excel的方法,其中需要下载PHPExcel插件,将其中的Classes文件夹改名为PHPExcel并提取到根文件夹外面,将两个文件夹一起放在所需项目中 使用PHPEx ...
- CodeForces - 95B
Petya loves lucky numbers. Everybody knows that positive integers are lucky if their decimal represe ...
- 牛客网Java刷题知识点之全局变量(又称成员变量,分为类变量和实例变量)、局部变量、静态变量(又称为类变量)
不多说,直接上干货! 定义类其实就是在定义类中的成员.成员:成员变量<-->属性,成员函数<-->行为. 局部变量在方法内部声明,并且只能在方法内部使用,在外层的方法被调用时被 ...
- cocos
cocos compile -p android --android-studio --app-abi=armeabi-v7a ./adb kill-server&& ./adb se ...
- pat1098. Insertion or Heap Sort (25)
1098. Insertion or Heap Sort (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...