一、认识graphviz
接触graphviz是几年前的一个项目,要画出数据网络的布局,使用graphviz能比较清楚的画出数据之间的关系。
可以在gallery中查看他能完成的图形:http://www.graphviz.org/gallery/。graphviz最方便的地方在于能够很快的清晰的画出点与点之间的关系,并且有许多布局算法能够很好的去布局。
之前使用它画过流程图,决策树。使用twopi画出数据的关联关系:
二、安装graphviz
官网下载:http://www.graphviz.org/download/。
根据自己的版本来选择:
安装在任意喜欢的位置。但是需要把安装目录的graphviz/bin
加入环境变量PATH
里,我这里只写了相对路径。
打开cmd,输入:dot --help
,如果弹出以下信息,就是安装成功:
三、使用graphviz
3.1 基本信息
graphviz中包含了众多的布局器:
dot 默认布局方式,主要用于有向图
neato 基于spring-model(又称force-based)算法
twopi 径向布局
circo 圆环布局
fdp 用于无向图
以上布局我都使用过,但是个人比较倾向dot和twopi,可以根据需求来画图。
基本语法
字符串 都要加双引号, 可以加\n换行符
注释 双斜杠// 或/* */
有向图 digraph, 节点关系: 指向->
无向图 graph, 节点关系: 连通 --
属性 node[attribute1=value1, attribute2=value2]
大小: size=”2,2”; 单位为英寸
标签: label=”显示在图上的内容”
边:edge [color=red,style=dotted]; 这句话之后生效
节点:node [color=navy]; 这句话之后生效
边方向:rankdir=参数值;LR(从左到右),RL,BT,TB
节点形状: a[shape=box]; 默认是椭圆
边框大小:a[width=.1,height=2.5]; 单位为英寸
边框颜色:a[color=red];
构造边
关系 | 有向图 | 无向图 |
一对一 | a->b; | a–b; |
一对多 | a->{b;c;d}; | a–{b;c;d}; |
多对一 | {b;c;d}->a; | {b;c;d}–a; |
多对多 | {m,n,p,q}->{b;c;d}; | {m,n,p,q}->{b;c;d} |
详细资料:
官方文档:http://www.graphviz.org/documentation/
属性设置:https://graphviz.gitlab.io/_pages/doc/info/attrs.html
节点形状:https://graphviz.gitlab.io/_pages/doc/info/shapes.html
箭头形状:https://graphviz.gitlab.io/_pages/doc/info/arrows.html
颜色配置:https://graphviz.gitlab.io/_pages/doc/info/colors.html
3.2 基本使用
以画一个dot布局为例子:
(1)建立一个first.dot脚本:
digraph first1{
a;
b;
c;
d;
a->b;
b->d;
c->d;
}
解释:digraph
是画图类型,接触高级使用可以有不同的类型,first2
可以和文件名first
不一样。画了abcd4个点。然后a->b
表示a点指向b点,如果有线条的指向,可以不用先声明点。即,上述代码等价于:
digraph first2{
a->b;
b->d;
c->d;
}
(2)画图
打开cmd到first.dot
目录下,运行:dot -Tpng first.dot -o first.png
可以得到画好的图形。
解释:dot
表示使用的是dot布局,其他布局相应的修改即可,-T
表示格式,即画成png格式,-o
表示重命名为first.png。
在这里如果出现syntax error
,可看第四部分常见问题解决。
(3)画图结果
上面的简单的代码得到以下结果:
一对多示例
digraph demo1 {
//解决中文乱码
node[fontname = "Microsoft YaHei"];
edge[fontname = "Microsoft YaHei"];
graph[fontname = "Microsoft YaHei"];
label="一对多示例"
{你} -> {
a;
b;
c;
};
}
关系
graph gvDemo1 {
a -- b
a -- b
b -- a [color=blue]
}
有向图
digraph gvDemo2 {
a -> b
a -> b
b -> a [color=blue style=filled]
}
多对多
digraph gvABC {
{ a b c } -> { d e f }
}
digraph gvDemo {
main -> parse -> execute;
main -> init;
main -> cleanup;
execute -> make_string;
execute -> printf
init -> make_string;
main -> printf;
execute -> compare;
}
digraph gvDemo{
node [peripheries=2 style=filled color="#eecc80"]
edge [color="sienna" fontcolor="green"]
main -> parse -> execute;
main -> init [arrowhead = box];
main -> cleanupi -> main;
make_string[label = once shape=parallelogram style=filled ]
execute -> make_string[label=Go style=dashed arrowtail=diamond];
execute -> printf [shape=box];
init -> make_string;
main -> printf[dir=none];
execute -> compare[dir=both];
}
digraph gvDemo3 {
edge[fontname="Microsoft YaHei"]
node[fontname="Microsoft YaHei"]
graph[fontname="Microsoft YaHei"]
label="游戏资源更新流程"
rankdir="TB"
start[label="启动游戏" shape=circle style=filled]
ifwifi[label="网络环境判断是否 WIFI" shape=diamond]
needupdate[label="是否有资源需要更新" shape=diamond]
startslientdl[label="静默下载" shape=box]
enterhall[label="进入游戏大厅" shape=box]
enterroom[label="进入房间" shape=box]
resourceuptodate[label="资源不完整" shape=diamond]
startplay[label="正常游戏" shape=circle fillcolor=blue]
warning[label="提醒玩家是否更新" shape=diamond]
startdl[label="进入下载界面" shape=box]
//{rank=same; needupdate, enterhall}
{shape=diamond; ifwifi, needupdate}
start -> ifwifi
ifwifi->needupdate[label="是"]
ifwifi->enterhall[label="否"]
needupdate->startslientdl[label="是"]
startslientdl->enterhall
needupdate->enterhall[label="否"]
enterhall -> enterroom
enterroom -> resourceuptodate
resourceuptodate -> warning[label="是"]
resourceuptodate -> startplay[label="否"]
warning -> startdl[label="确认下载"]
warning -> enterhall[label="取消下载"]
startdl -> enterhall[label="取消下载"]
startdl -> startplay[label="下载完成"]
}
graph gvDemo4{
"黑海" -- "亚速海";
"黑海" -- "博斯普鲁斯海峡"
"达达尼尔海峡" -- "爱琴海"
subgraph cluster_T{//新东西
label = "黑海海峡";//新东西
"达达尼尔海峡" -- "马尔马拉海" -- "博斯普鲁斯海峡";
}
subgraph cluster_M{
label = "地中海海域";
"中部地中海" -- {"爱琴海" "爱奥尼亚海" "西西里海峡"}; //也是新东西
"西部地中海" -- {"西西里海峡" "第勒尼安海" "利古里亚海" "伊比利海" "阿尔沃兰海"};
"爱奥尼亚海" -- "亚得里亚海";
"阿尔沃兰海" -- "直布罗陀海峡";
}
}
digraph G{
Country->Narrow;
Country->Middle;
Country->Large;
Narrow->small_underpopulated[label="small population"];
Narrow->small_overpopulated[label="large population"];顦
Large->vast_overpopulated[label="large population"];
Large->vast_underpopulated[label="small population"];
Middle->small_overpopulated[label="More than average"];顦
Middle->vast_underpopulated[label="Less than average"];
small_overpopulated->A[label="GDP:HIGH"];
small_overpopulated->B[label="GDP:LOW"];
vast_overpopulated->C[label="GDP:HIGH"];
vast_overpopulated->D[label="GDP:LOW"];
vast_underpopulated->E[label="GDP:HIGH"];
vast_underpopulated->F[label="GDP:LOW"];
F->F[label="NOT EXIST",color="red"];
small_underpopulated->G[label="GDP:HIGH"];
small_underpopulated->H[label="GDP:LOW"];
D->I[label="RoadScattered"];
D->Y[label="HighCoveraged"];
C->J[label="HighCoveraged"];
A->K[label="HighCoveraged"];
B->L[label="RoadScattered"];
G->M[label="HighCoveraged"];
H->H[label="Number Too Less",color="red"];
E->O[label="RoadScattered"];
E->P[label="HighCoveraged"];
M->Q[label="Both"];
K->R[label="Both"];
L->S[label="Oil More"];
O->T[label="Oil More"];
P->U[label="Both"];
J->V[label="Oil More"];
J->W[label="Both"];
K->X[label="Electricity More"];
I->Z[label="Neither"];
Y->1[label="Neither"];
Q->Q[color="red"];
R->R[color="red"];
X->X[color="red"];
S->S[color="red"];
T->T[color="red"];
U->U[color="red"];
V->V[color="red"];
W->W[color="red"];
Z->Z[color="red"];
1->1[label="Number Too Less",color="red"];
}
digraph G {
A -> B;
A -> C -> B;
A -> D -> B;
}
节点形状
digraph G {
size = "4, 4";
main [shape=box]; /* 这是注释 */
main -> parse [weight=8];
parse -> execute;
main -> init [style=dotted];
main -> cleanup;
execute -> { make_string; printf}
init -> make_string;
edge [color=red]; // 设置生效
main -> printf [style=bold,label="100 times"];
make_string [label="make a\n字符串"];
node [shape=box,style=filled,color=".7 .3 1.0"];
execute -> compare;
}
标签
digraph G {
a -> b -> c;
b -> d;
a [shape=polygon,sides=5,peripheries=3,color=lightblue,style=filled];
c [shape=polygon,sides=4,skew=.4,label="hello world"]
d [shape=invtriangle];
e [shape=polygon,sides=4,distortion=.7];
}
类似HTML的样式
digraph html {
abc [shape=none, margin=0, label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ROWSPAN="3"><FONT COLOR="red">hello</FONT><BR/>world</TD>
<TD COLSPAN="3">b</TD>
<TD ROWSPAN="3" BGCOLOR="lightgrey">g</TD>
<TD ROWSPAN="3">h</TD>
</TR>
<TR>
<TD>c</TD>
<TD PORT="here">d</TD>
<TD>e</TD>
</TR>
<TR>
<TD COLSPAN="3">f</TD>
</TR>
</TABLE>>];
}
二分查找树
digraph g {
node [shape = record,height=.1];
node0[label = "<f0> |<f1> G|<f2> "];
node1[label = "<f0> |<f1> E|<f2> "];
node2[label = "<f0> |<f1> B|<f2> "];
node3[label = "<f0> |<f1> F|<f2> "];
node4[label = "<f0> |<f1> R|<f2> "];
node5[label = "<f0> |<f1> H|<f2> "];
node6[label = "<f0> |<f1> Y|<f2> "];
node7[label = "<f0> |<f1> A|<f2> "];
node8[label = "<f0> |<f1> C|<f2> "];
"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;
}
示例
//定义节点属性
digraph g {
//==========定义节点关系============
a->b;
b->c;
c->a;
c->d->e->f;
d->g;
e->h;
//==========定义节点属性============
//定义a节点为长方形, 样式为填充, 填充颜色为#ABACBA
a[shape=box,label="Server1\nWebServer",fillcolor="#ABACBA",style=filled];
//定义b为5边形, 标签为"bb", 样式为填充, 填充色为red
b[shape=polygon,sides=5,label="bb",style=filled,fillcolor=red];
//c, 默认为椭圆
d[shape=circle]; //园
e[shape=triangle]; //三角形
f[shape=polygon, sides=4, skew=0.5]; //平行四边形
g[shape=polygon, distortion=0.5]; //梯形, 上边长
h[shape=polygon, distortion=-.5]; //梯形, 下边长
}
有向图
digraph g {
//edge[style=dashed]; //定义边的样式, 虚线
node[peripheries=2, style=filled, color="#eecc80"];
a->b [color=red, style=dashed]; //定义边的颜色, 红色 (b和方括号之间必须有空格)
b->c; //箭头, 三角形; 箭尾, 菱形
b->d [arrowhead=box]; //箭头, 长方形
b->e [dir=none]; //没有箭头
d->f [dir=both]; //双向箭头
f->h [label=go]; //定义edge的标签
f->k [arrowhead=diamond]; //更改箭头形状
k->y [headlabel="哈哈", taillabel="洗洗"];
}
无向图
graph g {
edge[style=dashed]; //定义边的样式, 虚线
a -- b [color=red]; //定义边的颜色, 红色 (b和方括号之间必须有空格)
}
ER图
digraph g {
graph [
rankdir = "LR"
];
node [
fontsize = "16"
shape = "ellipse"
];
edge [
];
"user" [
label = "User| <id> id|username|password|last|status"
shape = "record"
];
"profile" [
label = "Profile| <id> id | name | sex | age | address | icq | msn"
shape = "record"
];
user:id->profile:id [label="1:1"];
"category" [
label = "Category| <id> id | <pid> pid | name | status"
shape = "record"
];
category:pid->category:id [label="1:n"];
"article" [
label = "Article| <id> id| <user_id> user_id | <cid> category_id | title | content | datetime | status"
shape = "record"
];
article:user_id->user:id [label="1:n"];
article:cid->category:id [label="1:n"];
"feedback" [
label = "Feedback| <id> id| <user_id> user_id | <article_id> article_id | title | content | datetime | status"
shape = "record"
];
feedback:user_id->user:id [label="1:n"];
feedback:article_id->article:id [label="1:n"];
}
复杂标签
digraph graphname{
/* 把节点的形状设置为 record,默认的是圆角矩形 */
node [shape = record];
root [label = "left|middle|right"];
left [label = "one|two"];
right [label = "hello\nworld|{b|{c|d|e}|f}|g|h"];
root -> left;
root -> right;
}
3.3 高级使用
网上参考一篇博客,写的比较详细,对于很多应用场景都有提到: http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/
但是,想要查询每个属性的信息,可以看官网的查询文档:
Node, Edge and Graph Attributes(属性):https://graphviz.gitlab.io/_pages/doc/info/attrs.html
Node Shapes(节点形状):https://graphviz.gitlab.io/_pages/doc/info/shapes.html
Arrow Shapes(箭头形状):https://graphviz.gitlab.io/_pages/doc/info/arrows.html
四、常见问题
4.1 编译问题
如果遇见以下错误:
image.png
解决:
1、编码问题。
把文件另存为,'utf-8'或'ANSI'(不涉及中文使用时),看是否编译出问题。
2、对于文件格式的识别。
将文件开头加2个空格,其识别的时候,对于第一个字符,在windows下会问题,源于文件的编码格式。
4.2 中文问题
修改文件,Graphviz2.37\etc\fonts\fonts.conf
,安装的相对目录。
(1)文件修改
将下列代码:
<dir>#WINDOWSFONTDIR#</dir>
<dir>~/.fonts</dir>
修改为:
<dir>C:\WINDOWS\Fonts</dir>
<dir>~/.fonts</dir>
(2)文本设置
2.1 文本保存的编码为"utf-8"
2.2 文本中的字体设置
使用的dot
文件按照规则属性,设置fontname
属性即可:
fontname="Microsoft YaHei"
edge [fontname="Microsoft YaHei"];
node [fontname="Microsoft YaHei"];
digraph gvDemo3 {
edge[fontname="Microsoft YaHei"]
node[fontname="Microsoft YaHei"]
graph[fontname="Microsoft YaHei"]
}
以上分别是全局、边、节点的设置。
可用的中文,有很多:
黑体:SimHei
宋体:SimSun
新宋体:NSimSun
仿宋:FangSong
楷体:KaiTi
新细明体:PMingLiU
细明体:MingLiU
标楷体:DFKai-SB
微软正黑体:Microsoft JhengHei
微软雅黑体:Microsoft YaHei
2.3 dot
文件中的中文前后加空格
如:label="节点"
应为label=" 节点 "
Java中使用
//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;
/**
* <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.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="jabba.laci@gmail.com">jabba.laci@gmail.com</a>)
*/
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 = "C:\\Program Files (x86)\\Graphviz2.38\\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
import java.io.File;
public class GTest {
public static void main(String[] args){
GTest gtest = new GTest();
String[] nodes = {"A","B","C","D","E","F","G"};
String[] preline = {"B -> A","D -> B","E -> D","C -> E","G -> C","F -> G"};
gtest.start(nodes, preline);
}
private void start(String[] nodes,String[] preline){
Graphviz gv = new Graphviz();
//定义每个节点的style
String nodesty = "[shape = polygon, sides = 6, peripheries = 2, color = lightblue, style = filled]";
//String linesty = "[dir=\"none\"]";
gv.addln(gv.start_graph());//SATRT
gv.addln("edge[fontname=\"DFKai-SB\" fontsize=15 fontcolor=\"black\" color=\"brown\" style=\"filled\"]");
gv.addln("size =\"8,8\";");
//设置节点的style
for(int i=0;i<nodes.length;i++){
gv.addln(nodes[i]+" "+nodesty);
}
for(int i=0;i<preline.length;i++){
gv.addln(preline[i]+" "+" [dir=\"none\"]");
}
gv.addln(gv.end_graph());//END
//节点之间的连接关系输出到控制台
System.out.println(gv.getDotSource());
//输出什么格式的图片(gif,dot,fig,pdf,ps,svg,png,plain)
String type = "png";
//输出到文件夹以及命名
File out = new File("C:/Users/fanghui/Desktop/GraphTest/test." + type); // Linux
//File out = new File("c:/eclipse.ws/graphviz-java-api/out." + type); // Windows
gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), type ), out );
}
}
控制台输出
输出生成的图片
参考 :
https://www.jianshu.com/p/6d9bbbbf38b1
https://www.cnblogs.com/fanghuiplus/p/10072937.html