。java可以直接调用这个类实现画图功能,但是使用这个类的前提是你的电脑已经装了GraphViz软件,你可以在http://www.graphviz.org/Gallery.php下载windows版本,装完后,找到dot.exe所在的路径,我电脑上的是D:\Program Files\Graphviz2.30\bin\dot.exe,

将GraphViz.java中的这一路径改成你电脑上的路径,基本上就可以用了。

package Graphoutput;

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

/*$Id$*/

/*

******************************************************************************

* *

* (c) Copyright 2003 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.DataInputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FileWriter;

import java.io.InputStreamReader;

/**

*

*

Purpose: GraphViz Java API

*

*

*

Description:

*

With this Java class you can simply call dot

* from your Java programs

*

Example usage:

*

*

* 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 );

*

*

*

*

*

* @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 (jabba.laci@gmail.com)

*/

public class GraphViz

{

/**

* The dir. where temporary files will be created.

*/

//private static String TEMP_DIR = "/tmp"; // Linux

private static String TEMP_DIR = "c:/temp"; // Windows

/**

* Where is your dot program located? It will be called externally.

*/

// private static String DOT = "/usr/bin/dot"; // Linux

private static String DOT = "D:\\Program Files\\Graphviz2.30\\bin\\dot.exe"; // Windows

/**

* 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 graph.toString();

}

/**

* Adds a string to the graph's source (without newline).

*/

public void add(String line) {

graph.append(line);

}

/**

* Adds a string to the graph's source (with newline).

*/

public void addln(String line) {

graph.append(line + "\n");

}

/**

* Adds a newline to the graph's source.

*/

public void addln() {

graph.append('\n');

}

/**

* 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) { ioe.printStackTrace();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, 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.

*/

public File writeDotSourceToFile(String str) throws java.io.IOException

{

File temp;

try {

temp = File.createTempFile("graph_", ".dot.tmp", new File(GraphViz.TEMP_DIR));

FileWriter fout = new FileWriter(temp);

fout.write(str);

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 "}";

}

/**

* 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

通过下面这个类调用graphViz.java

import java.io.File;

public class Proba

{

public static void main(String[] args)

{

Proba p = new Proba();

p.start();

// p.start2();

}

/**

* Construct a DOT graph in memory, convert it

* to image and store the image in the file system.

*/

private void start()

{

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";

// String type = "dot";

// String type = "fig"; // open with xfig

// String type = "pdf";

// String type = "ps";

// String type = "svg"; // open with inkscape

// String type = "png";

// String type = "plain";

File out = new File("/tmp/out." + type); // Linux

// File out = new File("c:/eclipse.ws/graphviz-java-api/out." + type); // Windows

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

}

/**

* Read the DOT source from a file,

* convert to image and store the image in the file system.

*/

private void start2()

{

// String dir = "/home/jabba/eclipse2/laszlo.sajat/graphviz-java-api"; // Linux

// String input = dir + "/sample/simple.dot";

String input = "c:/eclipse.ws/graphviz-java-api/sample/simple.dot"; // Windows

GraphViz gv = new GraphViz();

gv.readSource(input);

System.out.println(gv.getDotSource());

String type = "gif";

// String type = "dot";

// String type = "fig"; // open with xfig

// String type = "pdf";

// String type = "ps";

// String type = "svg"; // open with inkscape

// String type = "png";

// String type = "plain";

File out = new File("/tmp/simple." + type); // Linux

// File out = new File("c:/eclipse.ws/graphviz-java-api/tmp/simple." + type); // Windows

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

}

}

Graphviz介绍

graphviz是贝尔实验室几个计算机牛人设计的一个开源 的图表(计算机科学中数据结构中的图)可视化项目,主要用C语言实现,主要实现了一些图布局算法。通过这些算法,可以将图中的节点在画布上比较均匀的分 布,缩短节点之间的边长,并且尽量的减少边的交叉。

graphviz提供命令式的绘图方式,它提供一个dot语言 用来编写绘图脚本,然后对这个脚本进行解析,分析出其中的定点,边以及子图,然后根据属性进行绘制。具体的可以看一个例子,这个例子来自官方的文档。

digraph G {

main -> parse -> execute;

main -> init;

main -> cleanup;

execute -> make_string;

execute -> printf

init -> make_string;

main -> printf;

execute -> compare;

}

digraph指定该图是一个有向图(directed graph),->表示一条边,main,parse,execute等是顶点,运行出来的效果很好看,如下图:

需要注意的是,我在这个dot脚本中没有指定任何的关于图的位置的信息,布局器会自动的根据图形的类型进行布局,并最终展现出来。

再来看一个比较复杂,并且是程序员经常使用的功能,数据结构图:

digraph g {

node [shape = record,height=.1];

node0[label = " | G| "];

node1[label = " | E| "];

node2[label = " | B| "];

node3[label = " | F| "];

node4[label = " | R| "];

node5[label = " | H| "];

node6[label = " | Y| "];

node7[label = " | A| "];

node8[label = " | C| "];

"node0":f2 ->"node4":f1;

"node0":f0 ->"node1":f1;

"node1":f0 ->"node2":f1;

"node1":f2 ->"node3":f1;

"node2":f2 ->"node8":f1;

"node2":f0 ->"node7":f1;

"node4":f2 ->"node6":f1;

"node4":f0 ->"node5":f1;

}

运行后的效果如下图所示:

不知道其他的程序员怎样,反正我对命令行情有独钟,比较喜欢这一类的工具。最早接触的计算机系统正是一个没有图形系统的BSD,由此对命令行的,没 有界面的程序都特别感兴趣。

相关的想法

自从使用了graphviz以后,一直想着把这个好东西移植到java下来,大概的思想跟graphviz类似:

解析dot脚本,生成图的对象,这个图中包括节点,边以及子图等对象,这些对象上都绑定着相应的属性

将解析出来的图对象发送给layout engine进行处理,layout engine可以选择布局策略,比如流布局等

从layout engine中得到布局后的图对象,并交给image engine处理,得到最终结果,负责展示或者保存等

dot 的语法定义比较简单,我已经用javacc构造了一个dot的分析器,现在可以从dot文件中构建出图对象出来,不过还需要进一步完善,可以看看这个 BNF定义:

graph -> [strict] (digraph|graph) id'{'stmt-list'}'

stmt-list -> [stmt [';'] [stmt-list] ]

stmt -> attr-stmt | node-stmt | edge-stmt | subgraph | id '='id

attr-stmt -> (graph | node | edge) attr-list

attr-list -> '['[a-list]']'[attr-list]

a-list -> id '='id [','][a-list]

node-stmt -> node-id [attr-list]

node-id -> id [port]

port -> port-location [port-angle] | port-angle [port-location]

port-location -> ':'id |':''('id','id')'

port-angle ->'@'id

edge-stmt -> (node-id | subgraph) edgeRHS [attr-list]

edgeRHS -> edgeop (node-id | subgraph) [edgeRHS]

subgraph -> [subgraph id] '{'stmt-list'}'| subgraph id

(最近老是感觉时间不够用,有很多有意思的项目要做,比如要完善前几天说的那个bbms(Bus Based Message Service), 再比如修改用Swing和Smack做一个jabber的客户端jTalk,都是很有搞头的,唉,扯远了。)

当然graphviz的功能不至于此,它提供一个lib,可以用来将绘图引擎嵌入在自己的应用中。这是一个很有意义的事,我们可以不必掌握布局部分 的复杂算法,把精力放在业务逻辑部分,将最后的图对象交给这个引擎来处理即可。当然,如果你正好和我一样,想了解其神奇的布局算法,不妨翻翻它的源码,欢 迎交流之至。

我在周末分析了下graphviz的内部结构,并建立了一个java的项目jraph,用来做简单的移植,主要是学习之用,其实,Java的图库还是相当丰富的,比如JGraph ,JGraphT,Prefuse,TouchGraph等等,用来做项目当然是很便捷的,但是我还是比较喜欢看着一个算法被自己实现的过程,特别是这种 比较神奇的算法,哈哈。

预期中的API如下:

publicstaticvoidmain(String[] args){

Parser parser = newGCodeParser("file.g");

GraphSet gs = parser.parse();

GraphSet layouted =

newGraphLayoutEngine(gs).layout();

ImageEngine imgEngine =

newGraphImageEngine(layouted);

imgEngine.export(0);

}

同graphviz一样,先调用分析器构造出图的集合GraphSet(包括多个图,每个图中包括Vertex,Edge,及SubGraph), 然后进行布局,最后将通过布局后的GraphSet绘制结果。目前完成了框架的设计部分,分析器部分基本完成,layout部分只实现了一个策略,即force-based布局算法,不过layout engine被设计成可以插拔的模型,如果有了新的算法实现,可以很容易的整合起来。

dot.exe  -Tpng -o new.png -Kdot new.dot

java 调用graphviz_java程序如何调用Graphviz相关推荐

  1. linux下java调用matlab程序,linux_java调用windows_matlab程序

    0 说明 本文为研究java和matlab的混合编程,进行了详细的测试和探索,以解决linux环境下java程序调用matlab程序的一个应用. linux端的环境 :(运行java程序并调用wind ...

  2. python3调用java_Python程序中调用Java代码的实践

    1.环境准备 windows 7(64位)+JDK(64位)+Python(64位)+eclipse+pycharm 还需要一个作为桥梁的工具包,jpype1,这个工具包可以启动jvm,使java代码 ...

  3. python调用java文件_Python程序中调用Java代码的实践

    1.环境准备 windows 7(64位)+JDK(64位)+Python(64位)+eclipse+pycharm 还需要一个作为桥梁的工具包,jpype1,这个工具包可以启动jvm,使java代码 ...

  4. java 调用casperjs_Java程序去调用并执行shell脚本及问题总结(推荐)

    摘要: 该文章来自阿里巴巴技术协会(ATA)精选集 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发. java开发的特点就是我们可以很早地进行TDDL, ME ...

  5. 存储过程系列之存储过程sql数据库调用和程序代码调用

    1.存储过程,无参数的存储过程 创建无参数存储存储过程 Create Procedure DCEMREMR_TEMPLATE As SELECT TOP 10 [FILENAME],[FILETITL ...

  6. java调用应用程序_java调用第三方应用程序

    1. java调用第三方应用使用 ProcessBuilder 对象来调用 例子位置: xc-service-manage-media-processor/test/TestProcessBuilde ...

  7. python调用matlab程序_Python调用MATLAB实现fmincon函数

    motivation: 1.要实现"符号几何规划"的功能,使用MATLAB自带的fmincon函数来实现 2.工程的代码是通过Python来完成的,需要Python调用MATLAB ...

  8. web调用服务器的exe文件,浏览器Web调用exe程序文件

    浏览器Web调用exe程序文件 Dwtowen • 2020 年 10 月 13 日 Loading... # 浏览器Web调用exe程序文件 ## IE 浏览器 在IE中可以使用ActiveXObj ...

  9. eclipse java调用c 代码吗_linux下通过eclipse开发用java调用c程序的方法

    linux下通过eclipse开发用java调用c程序的方法: 1.先建立好java工程并建立java文件如下: public class testso {     static {         ...

最新文章

  1. Pytorch中的序列化容器-度消失和梯度爆炸-nn.Sequential-nn.BatchNorm1d-nn.Dropout
  2. java enum判断_Java Enum枚举 遍历判断 四种方式(包括 Lambda 表达式过滤)
  3. Spring Cloud Greenwich 正式发布,Hystrix 即将寿终正寝!
  4. 启动定时器t0的工作指令是_第六章 习题
  5. 2018 总结 2019 展望
  6. 管道实现父子进程的信息传递(一)【fork函数、pipe函数、write/read操作、wait函数】
  7. LeetCode 804. 唯一摩尔斯密码词(哈希+set)
  8. vb软件使用时间限制_GTD时间管理软件Wunderlist使用心得总结
  9. 自动驾驶落地物流场景,嬴彻科技驶入快车道
  10. pyinstaller将py文件转成exe格式
  11. ImportError: libcudart.so.10.0: cannot open shared object file
  12. ftp协议是一种用于什么的协议_购房协议怎么写?签购房协议要注意什么
  13. 华为交换机镜像端口配置
  14. C语言跨平台游戏开发
  15. 华为eNSP-基本配置指令
  16. vscode python第三方库自动补全_vscode python 第三方库的智能提示
  17. 网络---协议(TCP/IP五层模型)
  18. Windows/Ubuntu搭建RTMP服务器+OBS推流+VLC拉流
  19. win10 退出误登的微软账号,无需改注册机,无需重置系统
  20. 反思:为什么你做淘宝客不赚钱

热门文章

  1. 成大事业、大学问者三境界
  2. 以时尚品牌作为名字的歌,都有大来头
  3. 《功夫熊猫》之经典台词~~
  4. Python的格式化输出方式
  5. python采集高德地图上商家信息代码(亲测OK)
  6. C# IQueryable 和 IEnumerable 的区别
  7. 体验大自然的魅力:奉贤自助烧烤篝火晚会团建,让你重拾生活的乐趣!
  8. 原生 和html5,H5和原生APP对比
  9. 数睿数据新签约6家合作伙伴,第六届山东软件生态大会顺利落幕
  10. java fileitem 识别图片大小_Java FileItem.getSize方法代碼示例