是否可以在Java中为C程序打印出诊断信息?

时间:2013-02-12 13:22:31

标签: java c eclipse compiler-construction mingw

我想从java程序编译以下C代码(故意留下语法错误):

/* Hello World program */

#include<stdio.h>

main()
{
    printf("Hello World")

}

我希望我的java程序编译C文件并在控制台中提供诊断信息。 示例:第4行;预期和第5行无效的语法...

我已经安装了CodeBlock MinGW编译器,并且能够编译代码并打印出错误。

看看我做了什么:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class C_Compile {
    public static void main(String args[]){

        String ret = compile();
        System.out.println(ret);

    }
    public static String compile()
    {
        String log="";
        String myDirectory = "C:\\";
        try {
            String s= null;
            //change this string to your compilers location
            Process p = Runtime.getRuntime().exec("cmd /C gcc hello.c", null, new java.io.File(myDirectory));

            BufferedReader stdError = new BufferedReader(new
                    InputStreamReader(p.getErrorStream()));
            boolean error=false;

            log+="\n....\n";
            while ((s = stdError.readLine()) != null) {
                log+=s;
                error=true;
                log+="\n";
            }
            if(error==false) log+="Compilation Successful !!!";

        } catch (IOException e) {
            e.printStackTrace();
        }
        return log;
    }


    public int runProgram()
    {
        int ret = -1;
        try
        {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec("cmd.exe /c start a.exe");
            proc.waitFor();
            ret = proc.exitValue();
        } catch (Throwable t)
        {
            t.printStackTrace();
            return ret;
        }
        return ret;
    }
}

我得到了以下结果:

    ....
hello.c: In function 'main':
hello.c:9:1: error: expected ';' before '}' token

但我想知道是否有可能从听众那里获得诊断。我想得到行号,位置,语法错误的类型,稍后将在数组中输入以进行进一步处理。

以下是我在Java中想要的内容:

http://prntscr.com/sgvya

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    List<CaptureErrors> myerrors = new ArrayList<CaptureErrors>();
    MyDiagnosticListener listener = new MyDiagnosticListener(); 
    StandardJavaFileManager fileManager  = compiler.getStandardFileManager(listener, null, null); 

    String fileToCompile = "C:\\Users\\User\\Desktop\\MyC.java";

    Iterable fileObjects = fileManager.getJavaFileObjectsFromStrings(Arrays.asList(fileToCompile));  
    CompilationTask task = compiler.getTask(null, fileManager, listener, null, null, fileObjects); 
    Boolean result = task.call();
    if(result == true){
        System.out.println("Compilation has succeeded");
    }
    myerrors = listener.getlistofErrors();
    for (CaptureErrors e : myerrors)
    {
        System.out.println("Code: " + e.getCode());
        System.out.println("Kind: " + e.getKind());
        System.out.println("Line Number: " + e.getLinenumber());
       // System.out.println("Message: "+ e.getMessage(Locale.ENGLISH));
        //System.out.println("Source: " + e.getSource());
        System.out.println("End position: "+ e.getEndposition());
        System.out.println("Position: "+ e.getPosition());
        System.out.println("\n");

    }

1 个答案:

答案 0 :(得分:1)

代替Runtime.exec()使用ProcessBuilderredirectErrorStream(true)。这样,您就可以从编译器输出中捕获 stdout stderr 。而不是通过cmd /c调用直接从ProcessBuilder调用 gcc 可执行文件。检查子进程的exit code状态。非0 exitcode通常意味着子进程中的一些错误。然后使用一些正则表达式从输出流中提取错误消息和行号(这也包含gcc.exe的stderr输出)。