一、認識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="[email protected]">[email protected]</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