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 ...
随机推荐
- c++第六次实验
part 1 验证性实验 合并两个文件.虽说验证,但后两个实验均受该代码指导启发. part 2 文末添加数据 1.代码 #include<fstream> #include<io ...
- Unity 2018中的图形渲染
https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247490249&idx=1&sn=d86083e33d9884 ...
- 猜拳游戏三局两胜------java实现代码
package com.javasm.exerices02; import java.util.ArrayList; import java.util.List; import java.util.R ...
- 【数据库】SQL注入攻击
背景: 机房收费系统验收的时候,师父提到SQL注入攻击.自己以前看过类似的博客大概知道一些这方面的事情,于是自己动手查了查. 定义: 所谓SQL注入,通过SQL命令插入到Web表单提交或者输入域名或页 ...
- matplotlib.pyplot import报错: ValueError: _getfullpathname: embedded null character in path
Environment: Windows 10, Anaconda 3.6 matplotlib 2.0 import matplotlib.pyplot 报错: ValueError: _getfu ...
- 洛谷P3193 [HNOI2008]GT考试(KMP,矩阵)
传送门 大佬讲的真吼->这里 首先考虑dp,设$f[i][j]$表示长串匹配到第$i$位,短串最多匹配到$j$位时的方案数 那么答案就是$\sum_{i=0}^{m-1}f[n][i]$ 然后考 ...
- php使用百度地图API
首先注册百度开发者平台账号,创建应用获取AK 不同的应用功能不同,一定要注意,没有的功能调用会提示APP被禁用 根据开发文档使用 给出例子:百度地图WEB api http://lbsyun.baid ...
- springboot 简单自定义starter - beetl
使用idea新建springboot项目beetl-spring-boot-starter 首先添加pom依赖 packaging要设置为jar不能设置为pom<packaging>jar ...
- MYSQL性能优化之Mysql数据库监控
监控对象 数据库可用性监控数据库进程或是端口存在并不意味着数据库就是可用的 也就是说登陆服务器,并且能正确执行mysql命令 数据库性能 QPS和DPS并发线程数量(同时执行sql语句的数量,不是连接 ...
- WebP图片格式
腾讯科技讯 科技博客GigaOM近日撰文称,谷歌(微博)试图让WebP图片格式取代JPEG等现有图片格式.虽然谷歌无法很快达成所愿,但WebP仍然会对互联网产生重大影响. 文章全文如下: 受够了 ...