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 ...
随机推荐
- 图解linux安装hadoop
安装步骤: 一.准备工作 1.解压文件 [root@localhost soft]# tar -zxvf hadoop-2.4.1.tar.gz 2.改名: [root@localhost soft] ...
- 解读人:李琼,Metabolic profiling of tumors, sera and skeletal muscles from an orthotopic murine model of gastric cancer associated-cachexia(胃癌相关恶病质的原位小鼠模型中肿瘤,血清和骨骼肌的代谢谱分析)
发表时间:(2019年4月) IF:3.950 单位: 厦门大学 厦门理工大学 物种:小鼠的肿瘤,血清和骨骼肌 技术:核磁共振代谢组学分析 一. 概述:(用精炼的语言描述文章的整体思路及结果) 本研究 ...
- php静态方法和属性
静态方法和属性由static关键字定义 静态方法和属性不用实例化也可以直接访问,如 self::test(),self::tt 类实例化后可以访问静态方法,但是不可以访问静态属性 声明类属性或方法为静 ...
- 解决Nginx启动失败
一.Nginx下载http://nginx.org/en/download.html 二.Nginx启动失败原因1.本人下载的是nginx-1.12.1(稳定版),下载完解压后,进入路径中,start ...
- 如何简单的理解TDD与DDT
TDD:TEST-DRIVEN Development 测试驱动开发究竟是什么意思?如何理解测试驱动开发? 举个红绿条简单的例子: 1.编写测试代码 2.编译运行测试代码,肯定会失败,因为实现代码还没 ...
- Extending JMeter – Creating Custom Config Element – Property File Reader
JMeter is one of the best open source tools in the Test Automation Community. It comes with all the ...
- Hadoop InputFormat详解
InputFormat是MapReduce编程模型包括5个可编程组件之一,其余4个是Mapper.Partitioner.Reducer和OutputFormat. 新版Hadoop InputFor ...
- Storm概念学习系列 之Worker工作者进程
不多说,直接上干货! Worker工作者进程 工作者进程(Worker)是一个java进程,执行拓扑的一部分任务.一个Worker进程执行一个Topology的子集,它会启动一个或多个Execut ...
- 使用PHP导入Excel和导出数据为Excel文件
有时需要将Excel表格的数据导入到mysql数据库中,我们使用PHP的一个开源项目PHP-ExcelReader可以轻松实现Excel的导入.另外将mysql数据导出为Excel与本站上篇文章中导出 ...
- pat1097. Deduplication on a Linked List (25)
1097. Deduplication on a Linked List (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 ...