There is a test program in C # VS 2017 that draws a graph using GraphViz. Can not make friends with Russian characters, displayed abracadabra. Tell me how to teach GraphViz to work with Russian letters, can anyone come across it already?

DOT main code and text:

namespace GraphVizTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { String GrapgVizString = @"digraph g {ratio = fill; node[style = filled] label = ""Andre van Dun ""; InitialInitial->AwaitingAnalysis[color=""0.650 0.700 0.700""] [label =<<B>manual+</B>>]; subgraph cluster0 {label = ""Initial ""; GroomingGrooming->GroomingFinished[label =""manual""]; GroomingFinished[color=""0.449 0.447 1.000""]Groomingnever[color=""0.000 1.000 1.000""] } AwaitingAnalysis[color=""0.590 0.273 1.000""] AwaitingAnalysis->AwaitingDevelopment[color=""0.650 0.700 0.700""][label =""manual""]; AwaitingDevelopment[color=""0.590 0.273 1.000""] AwaitingDevelopment->InDevelopment[color=""0.650 0.700 0.700""] [label =""**МОЙ ТЕКСТ**""]; AwaitingDevelopment->AwaitingDelivery[color=""0.650 0.700 0.700""] [label =""manual""]; InDevelopment[color=""0.590 0.273 1.000""] InDevelopment->AwaitingDelivery[color=""0.650 0.700 0.700""] [label =""manual""]; AwaitingDelivery[color=""0.449 0.447 1.000""]}"; ///Option 1 //pictureBox1.Image = Examples.Run(GrapgVizString); ///Option 2 pictureBox1.Image = Examples.Graphviz.RenderImage(GrapgVizString, "jpg"); this.Size = pictureBox1.Image.Size; } } } 

Class Code:

 namespace GraphVizTest { public static class Examples { /// <summary> /// OPTION 1 /// </summary> /// <param name="dot"></param> /// <returns></returns> public static Image Run(string dot) { string executable = @".\external\dot.exe"; string output = @".\external\tempgraph"; File.WriteAllText(output, dot); System.Diagnostics.Process process = new System.Diagnostics.Process(); // Stop the process from opening a new window process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; // Setup executable and parameters process.StartInfo.FileName = executable; process.StartInfo.Arguments = string.Format(@"{0} -Tjpg -O -Tps:cairo", output); // Go process.Start(); // and wait dot.exe to complete and exit process.WaitForExit(); Image image; using (Stream bmpStream = System.IO.File.Open(output + ".jpg", System.IO.FileMode.Open)) { image = Image.FromStream(bmpStream); } File.Delete(output); File.Delete(output + ".jpg"); return image; } /// <summary> /// OPTION 2 /// </summary> public static class Graphviz { public const string LIB_GVC = @".\external\gvc.dll"; public const string LIB_GRAPH = @".\external\cgraph.dll"; public const int SUCCESS = 0; /// /// Creates a new Graphviz context. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr gvContext(); /// /// Releases a context's resources. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern int gvFreeContext(IntPtr gvc); /// /// Reads a graph from a string. /// [DllImport(LIB_GRAPH, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr agmemread(string data); /// /// Releases the resources used by a graph. /// [DllImport(LIB_GRAPH, CallingConvention = CallingConvention.Cdecl)] public static extern void agclose(IntPtr g); /// /// Applies a layout to a graph using the given engine. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern int gvLayout(IntPtr gvc, IntPtr g, string engine); /// /// Releases the resources used by a layout. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern int gvFreeLayout(IntPtr gvc, IntPtr g); /// /// Renders a graph to a file. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern int gvRenderFilename(IntPtr gvc, IntPtr g, string format, string fileName); /// /// Renders a graph in memory. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern int gvRenderData(IntPtr gvc, IntPtr g, string format, out IntPtr result, out int length); /// /// Release render resources. /// [DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)] public static extern int gvFreeRenderData(IntPtr result); public static Image RenderImage(string source, string format) { // Create a Graphviz context IntPtr gvc = gvContext(); if (gvc == IntPtr.Zero) throw new Exception("Failed to create Graphviz context."); // Load the DOT data into a graph IntPtr g = agmemread(source); if (g == IntPtr.Zero) throw new Exception("Failed to create graph from source. Check for syntax errors."); // Apply a layout if (gvLayout(gvc, g, "dot") != SUCCESS) throw new Exception("Layout failed."); IntPtr result; int length; // Render the graph if (gvRenderData(gvc, g, format, out result, out length) != SUCCESS) throw new Exception("Render failed."); // Create an array to hold the rendered graph byte[] bytes = new byte[length]; // Copy the image from the IntPtr Marshal.Copy(result, bytes, 0, length); // Free up the resources gvFreeRenderData(result); gvFreeLayout(gvc, g); agclose(g); gvFreeContext(gvc); using (MemoryStream stream = new MemoryStream(bytes)) { return Image.FromStream(stream); } } } } } 

enter image description here

  • Tell me, what is the encoding of the file which contains the label =""**МОЙ ТЕКСТ**"" ? - AK
  • one
    There is a graph here: habr.com/post/147843 and in accordance with it, look for what encoding you are trying to slip into it instead of your own. I recommend trying to send UTF8 there, and not your windows encoding - test123
  • To the text of the module file in the encoding: Unicode (UTF-8, with signature, code. Page 65001). - Rusanov Mikhail
  • And a variable of type System.String in which the text of the graph description is stored in UTF-16. - Rusanov Mikhail
  • If you draw a test graph in the program itself, the characters will be displayed normally? - user227049 pm

1 answer 1

Understood. I decided this way: I convectively text the description of the graph from 1251 into utf-8 before loading into the component (sample code below). Thanks @ test123 for the tip.

 public byte[] RenderImage(string source, string format) { // Create a Graphviz context IntPtr gvc = gvContext(); if (gvc == IntPtr.Zero) throw new Exception("Failed to create Graphviz context."); //+upd преобразуем в utf-8, иначе GraphViz отображает русские символы, как кракозябры Encoding utf8 = Encoding.GetEncoding("utf-8"); Encoding win1251 = Encoding.GetEncoding("windows-1251"); byte[] utf8Bytes = win1251.GetBytes(source); byte[] win1251Bytes = Encoding.Convert(win1251, utf8, utf8Bytes); source = win1251.GetString(win1251Bytes); //-upd // Load the DOT data into a graph IntPtr g = agmemread(source); if (g == IntPtr.Zero) throw new Exception("Failed to create graph from source. Check for syntax errors."); ... }