如何从 Java 调用 GraphViz

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26481910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 02:36:42  来源:igfitidea点击:

How to call GraphViz from java

javagraphviz

提问by user3534517

How to call GraphViz from java and how to call GraphViz functions using java? What are the necessary jar files that are to be included inorder to access the GraphViz library for building a dot graph? Is there any sample program for generating a dot graph

如何从java调用GraphViz以及如何使用java调用GraphViz函数?为了访问 GraphViz 库以构建点图,需要包含哪些 jar 文件?有没有生成点图的示例程序

采纳答案by seteropere

Check thisAPI, It is simple and has several output format (i.e. pdf gif ..etc).

检查这个API,它很简单并且有几种输出格式(即pdf gif ..etc)。

EDIT May 2016:As many commented that the API is not available anymore; Here its source code:

2016 年 5 月编辑:许多评论说 API 不再可用;这是它的源代码:

First there is config.propertiesfile that you need to create and copy paste the following:

首先是config.properties您需要创建的文件并复制粘贴以下内容:

##############################################################
#                    Linux Configurations                    #
##############################################################
# The dir. where temporary files will be created.
tempDirForLinux = /tmp
# Where is your dot program located? It will be called externally.
dotForLinux = /usr/bin/dot

##############################################################
#                   Windows Configurations                   #
##############################################################
# The dir. where temporary files will be created.
tempDirForWindows = c:/temp
# Where is your dot program located? It will be called externally.
dotForWindows = "c:/Program Files (x86)/Graphviz 2.28/bin/dot.exe"

##############################################################
#                    Mac Configurations                      #
##############################################################
# The dir. where temporary files will be created.
tempDirForMacOSX = /tmp
# Where is your dot program located? It will be called externally.
dotForMacOSX = /usr/local/bin/dot

Then Graphviz.java source code

然后Graphviz.java源代码

// GraphViz.java - a simple API to call dot from Java programs

/*$Id$*/
/*
 ******************************************************************************
 *                                                                            *
 *                    (c) Copyright Laszlo Szathmary                          *
 *                                                                            *
 * This program is free software; you can redistribute it and/or modify it    *
 * under the terms of the GNU Lesser General Public License as published by   *
 * the Free Software Foundation; either version 2.1 of the License, or        *
 * (at your option) any later version.                                        *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public    *
 * License for more details.                                                  *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with this program; if not, write to the Free Software Foundation,    *
 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                              *
 *                                                                            *
 ******************************************************************************
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.Properties;

/**
 * <dl>
 * <dt>Purpose: GraphViz Java API
 * <dd>
 *
 * <dt>Description:
 * <dd> With this Java class you can simply call dot
 *      from your Java programs.
 * <dt>Example usage:
 * <dd>
 * <pre>
 *    GraphViz gv = new GraphViz();
 *    gv.addln(gv.start_graph());
 *    gv.addln("A -> B;");
 *    gv.addln("A -> C;");
 *    gv.addln(gv.end_graph());
 *    System.out.println(gv.getDotSource());
 *
 *    String type = "gif";
 *    File out = new File("out." + type);   // out.gif in this example
 *    gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), type ), out );
 * </pre>
 * </dd>
 *
 * </dl>
 *
 * @version v0.5.1, 2013/03/18 (March) -- Patch of Juan Hoyos (Mac support)
 * @version v0.5, 2012/04/24 (April) -- Patch of Abdur Rahman (OS detection + start subgraph + 
 * read config file)
 * @version v0.4, 2011/02/05 (February) -- Patch of Keheliya Gallaba is added. Now you
 * can specify the type of the output file: gif, dot, fig, pdf, ps, svg, png, etc.
 * @version v0.3, 2010/11/29 (November) -- Windows support + ability to read the graph from a text file
 * @version v0.2, 2010/07/22 (July) -- bug fix
 * @version v0.1, 2003/12/04 (December) -- first release
 * @author  Laszlo Szathmary (<a href="[email protected]">[email protected]</a>)
 */
public class GraphViz
{
    /**
     * Detects the client's operating system.
     */
    private final static String osName = System.getProperty("os.name").replaceAll("\s","");

    /**
     * Load the config.properties file.
     */
    private final static String cfgProp = "/Users/seteropere/NetBeansProjects/TestApplication/src/config.properties";
    private final static Properties configFile = new Properties() {
        private final static long serialVersionUID = 1L; {
            try {
                load(new FileInputStream(cfgProp));
            } catch (Exception e) {}
        }
    };

    /**
     * The dir. where temporary files will be created.
     */
  private static String TEMP_DIR = "/Users/seteropere/NetBeansProjects/TestApplication";

    /**
     * Where is your dot program located? It will be called externally.
     */
  private static String DOT = configFile.getProperty("dotFor" + osName);

    /**
     * The image size in dpi. 96 dpi is normal size. Higher values are 10% higher each.
     * Lower values 10% lower each.
     * 
     * dpi patch by Peter Mueller
     */
    private int[] dpiSizes = {46, 51, 57, 63, 70, 78, 86, 96, 106, 116, 128, 141, 155, 170, 187, 206, 226, 249};

    /**
     * Define the index in the image size array.
     */
    private int currentDpiPos = 7;

    /**
     * Increase the image size (dpi).
     */
    public void increaseDpi() {
        if ( this.currentDpiPos < (this.dpiSizes.length - 1) ) {
            ++this.currentDpiPos;
        }
    }

    /**
     * Decrease the image size (dpi).
     */
    public void decreaseDpi() {
        if (this.currentDpiPos > 0) {
            --this.currentDpiPos;
        }
    }

    public int getImageDpi() {
        return this.dpiSizes[this.currentDpiPos];
    }

    /**
     * The source of the graph written in dot language.
     */
    private StringBuilder graph = new StringBuilder();

    /**
     * Constructor: creates a new GraphViz object that will contain
     * a graph.
     */
    public GraphViz() {
    }

    /**
     * Returns the graph's source description in dot language.
     * @return Source of the graph in dot language.
     */
    public String getDotSource() {
        return this.graph.toString();
    }

    /**
     * Adds a string to the graph's source (without newline).
     */
    public void add(String line) {
        this.graph.append(line);
    }

    /**
     * Adds a string to the graph's source (with newline).
     */
    public void addln(String line) {
        this.graph.append(line + "\n");
    }

    /**
     * Adds a newline to the graph's source.
     */
    public void addln() {
        this.graph.append('\n');
    }

    public void clearGraph(){
        this.graph = new StringBuilder();
    }

    /**
     * Returns the graph as an image in binary format.
     * @param dot_source Source of the graph to be drawn.
     * @param type Type of the output image to be produced, e.g.: gif, dot, fig, pdf, ps, svg, png.
     * @return A byte array containing the image of the graph.
     */
    public byte[] getGraph(String dot_source, String type)
    {
        File dot;
        byte[] img_stream = null;

        try {
            dot = writeDotSourceToFile(dot_source);
            if (dot != null)
            {
                img_stream = get_img_stream(dot, type);
                if (dot.delete() == false) 
                    System.err.println("Warning: " + dot.getAbsolutePath() + " could not be deleted!");
                return img_stream;
            }
            return null;
        } catch (java.io.IOException ioe) { return null; }
    }

    /**
     * Writes the graph's image in a file.
     * @param img   A byte array containing the image of the graph.
     * @param file  Name of the file to where we want to write.
     * @return Success: 1, Failure: -1
     */
    public int writeGraphToFile(byte[] img, String file)
    {
        File to = new File(file);
        return writeGraphToFile(img, to);
    }

    /**
     * Writes the graph's image in a file.
     * @param img   A byte array containing the image of the graph.
     * @param to    A File object to where we want to write.
     * @return Success: 1, Failure: -1
     */
    public int writeGraphToFile(byte[] img, File to)
    {
        try {
            FileOutputStream fos = new FileOutputStream(to);
            fos.write(img);
            fos.close();
        } catch (java.io.IOException ioe) { return -1; }
        return 1;
    }

    /**
     * It will call the external dot program, and return the image in
     * binary format.
     * @param dot Source of the graph (in dot language).
     * @param type Type of the output image to be produced, e.g.: gif, dot, fig, pdf, ps, svg, png.
     * @return The image of the graph in .gif format.
     */
    private byte[] get_img_stream(File dot, String type)
    {
        File img;
        byte[] img_stream = null;

        try {
            img = File.createTempFile("graph_", "."+type, new File(GraphViz.TEMP_DIR));
            Runtime rt = Runtime.getRuntime();

            // patch by Mike Chenault
            String[] args = {DOT, "-T"+type, "-Gdpi="+dpiSizes[this.currentDpiPos], dot.getAbsolutePath(), "-o", img.getAbsolutePath()};
            Process p = rt.exec(args);

            p.waitFor();

            FileInputStream in = new FileInputStream(img.getAbsolutePath());
            img_stream = new byte[in.available()];
            in.read(img_stream);
            // Close it if we need to
            if( in != null ) in.close();

            if (img.delete() == false) 
                System.err.println("Warning: " + img.getAbsolutePath() + " could not be deleted!");
        }
        catch (java.io.IOException ioe) {
            System.err.println("Error:    in I/O processing of tempfile in dir " + GraphViz.TEMP_DIR+"\n");
            System.err.println("       or in calling external command");
            ioe.printStackTrace();
        }
        catch (java.lang.InterruptedException ie) {
            System.err.println("Error: the execution of the external program was interrupted");
            ie.printStackTrace();
        }

        return img_stream;
    }

    /**
     * Writes the source of the graph in a file, and returns the written file
     * as a File object.
     * @param str Source of the graph (in dot language).
     * @return The file (as a File object) that contains the source of the graph.
     */
    private File writeDotSourceToFile(String str) throws java.io.IOException
    {
        File temp;
        try {
            temp = File.createTempFile("dorrr",".dot", new File(GraphViz.TEMP_DIR));
            FileWriter fout = new FileWriter(temp);
            fout.write(str);
                       BufferedWriter br=new BufferedWriter(new FileWriter("dotsource.dot"));
                       br.write(str);
                       br.flush();
                       br.close();
            fout.close();
        }
        catch (Exception e) {
            System.err.println("Error: I/O error while writing the dot source to temp file!");
            return null;
        }
        return temp;
    }

    /**
     * Returns a string that is used to start a graph.
     * @return A string to open a graph.
     */
    public String start_graph() {
        return "digraph G {";
    }

    /**
     * Returns a string that is used to end a graph.
     * @return A string to close a graph.
     */
    public String end_graph() {
        return "}";
    }

    /**
     * Takes the cluster or subgraph id as input parameter and returns a string
     * that is used to start a subgraph.
     * @return A string to open a subgraph.
     */
    public String start_subgraph(int clusterid) {
        return "subgraph cluster_" + clusterid + " {";
    }

    /**
     * Returns a string that is used to end a graph.
     * @return A string to close a graph.
     */
    public String end_subgraph() {
        return "}";
    }

    /**
     * Read a DOT graph from a text file.
     * 
     * @param input Input text file containing the DOT graph
     * source.
     */
    public void readSource(String input)
    {
        StringBuilder sb = new StringBuilder();

        try
        {
            FileInputStream fis = new FileInputStream(input);
            DataInputStream dis = new DataInputStream(fis);
            BufferedReader br = new BufferedReader(new InputStreamReader(dis));
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            dis.close();
        } 
        catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }

        this.graph = sb;
    }

} // end of class GraphViz

An example is:

一个例子是:

public static void createDotGraph(String dotFormat,String fileName)
{
    GraphViz gv=new GraphViz();
    gv.addln(gv.start_graph());
    gv.add(dotFormat);
    gv.addln(gv.end_graph());
   // String type = "gif";
    String type = "pdf";
  // gv.increaseDpi();
    gv.decreaseDpi();
    gv.decreaseDpi();
    File out = new File(fileName+"."+ type); 
    gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), type ), out );
}

Invoking it like this:

像这样调用它:

    public static void main(String[] args) throws Exception {
        String dotFormat="1->2;1->3;1->4;4->5;4->6;6->7;5->7;3->8;3->6;8->7;2->8;2->5;";
        createDotGraph(dotFormat, "DotGraph");
 }

which will create dotsource.dotand DotGraph.pdfrepresenting a cubic graph in the directory you specified. Remember: you just need to change the values of two parameters in the code: cfgPropand TEMP_DIR.

这将在您指定的目录中创建dotsource.dotDotGraph.pdf表示立方图。请记住:您只需要更改代码中两个参数的值:cfgPropTEMP_DIR

Hope that helps.

希望有帮助。

回答by omerio

I've answered similar question here: Calling Graphviz dot from Java

我在这里回答了类似的问题: Calling Graphviz dot from Java

You can use the Graphviz Java APIclass which is a wrapper for Runtime.exec(), this is if you have the dot binaries on the same server as your Java App.

您可以使用Graphviz Java API类,它是 Runtime.exec() 的包装器,前提是您在 Java 应用程序所在的服务器上拥有点二进制文件。

If you don't have dot installed on the server or if you are using an environment like Google AppEngine where you can't install dot binaries locally then you can use Graphviz Server, a lightweight Java based HTTP server, you still need to install the dot binaries on the server on which you run Graphviz Server.

如果您没有在服务器上安装 dot,或者您使用的环境如 Google AppEngine 无法在本地安装 dot 二进制文件,那么您可以使用Graphviz Server,这是一个基于 Java 的轻量级 HTTP 服务器,您仍然需要安装运行 Graphviz Server 的服务器上的 dot 二进制文件。

The following is a code example using the Graphviz Java APIclass

以下是使用Graphviz Java API类的代码示例

// graphTypeis one of: pdf, svg, png, etc...

private static final String TEMP_PATH = "/tmp/graph.";

private File generateGraph(String dot, String graphType) {

    GraphViz gv = new GraphViz();
    gv.readString(dot);

    File out = new File(TEMP_PATH + graphType);   // Linux

    gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), graphType ), out );

    return out;
}

回答by Fabich

There seems to be a solution for graphviz in java without dot binary: https://github.com/nidi3/graphviz-java

java中的graphviz似乎有一个没有点二进制的解决方案:https: //github.com/nidi3/graphviz-java

From the github page it says:

从github页面它说:

To execute the graphviz layout engine, one of these options is used:

  • If the machine has graphviz installed and a dot command is available, spawn a new process running dot.
  • Use this javascript version of graphviz and execute it on the V8 javascript engine. This is done with the bundled J2V8 library.
  • Alternatively, the javascript can be executed on Java's own Nashorn or GraalVM engine.

要执行 graphviz 布局引擎,请使用以下选项之一:

  • 如果机器安装了 graphviz 并且 dot 命令可用,则生成一个运行 dot 的新进程。
  • 使用这个 javascript 版本的 graphviz 并在 V8 javascript 引擎上执行它。这是通过捆绑的 J2V8 库完成的。
  • 或者,javascript 可以在 Java 自己的 Nashorn 或 GraalVM 引擎上执行。

I have not tested it yet though

我还没有测试过