遇到doxygen生成的chm文档目录如果有中文是乱码?
原因不在于doxygen,它没有问题,问题出在微软的HTML Help Workshop的hhc.exe不支持utf8.所以要解决这个问题,需要做两个额外的步骤:
1.将html/index.hhp中的Language=0x409 English (United States)换成Language=0x804 中文 (中国),并将文本存成UTF8格式。
2.将html/index.hhc整个文件从UTF8编码换成gb2312,再次手动调用hhc.exe去处理这个hhp文件即可生成不是乱码的中文chm帮助文档。
我自己用C#写了个小工具来处理这个过程,源代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Diagnostics; namespace Generator { class Program { static void Main(string[] args) { if(args.Length <=0) { Console.WriteLine("Error:缺少目标配置文件"); return; } string path = args[0]; if(!File.Exists(path)) { Console.WriteLine(string.Format("{0}不存在", path)); return; } using(ChmGenerator generator = new ChmGenerator(path)) { generator.Generate(); } } } public class ChmGenerator : IDisposable { static readonly string HHC_CONFIG_LOCATION = "HHC_LOCATION = \"C:/Program Files (x86)/HTML Help Workshop/hhc.exe\""; string WorkDirectory; string InputFile; string ConfigText; string NewHHCConfig; string NewConfigText; string NewConfigPath; string HHCLocation; string DoxygenPath; string IntermediatePath; string IntermediateHHP; string IntermediateHHC; public ChmGenerator(string inputFile) { InputFile = inputFile; string Directory = Path.GetDirectoryName(InputFile); WorkDirectory = Directory; System.IO.Directory.SetCurrentDirectory(WorkDirectory); HHCLocation = Path.Combine(Directory, "hhc.exe"); DoxygenPath = Path.Combine(Directory, "doxygen.exe"); IntermediatePath = Path.Combine(Directory, "Intermediate"); IntermediateHHP = Path.Combine(IntermediatePath, @"html/index.hhp"); IntermediateHHC = Path.Combine(IntermediatePath, @"html/index.hhc"); NewHHCConfig = string.Format("HHC_LOCATION = \"{0}\"", HHCLocation); } public void Dispose() { try { if (!string.IsNullOrEmpty(NewConfigPath) && File.Exists(NewConfigPath)) { File.Delete(NewConfigPath); } } finally { } } public void Generate() { ConfigText = File.ReadAllText(InputFile, Encoding.UTF8); NewConfigPath = Path.Combine(WorkDirectory, Guid.NewGuid().ToString() + ".doxygenProj"); NewConfigText = ConfigText.Replace(HHC_CONFIG_LOCATION, NewHHCConfig); File.WriteAllText(NewConfigPath, NewConfigText, Encoding.UTF8); // 调用doxygen来生成 StartProc(DoxygenPath, string.Format(" {0}", NewConfigPath)); if(!PrepareInputFiles()) { Console.WriteLine("无法正确生成chm"); return; } // 调用hhc生成chm StartProc(HHCLocation, string.Format(" {0}", IntermediateHHP)); } private bool PrepareInputFiles() { // 替换Language if (File.Exists(IntermediateHHP)) { ReplaceFileText(IntermediateHHP, "Language=0x409 English (United States)", "Language=0x804 中文 (中国)", Encoding.UTF8); if (File.Exists(IntermediateHHC)) { ChangeFileToAnsi(IntermediateHHC, Encoding.UTF8, Encoding.GetEncoding("gb2312")); return true; } else { Console.WriteLine(string.Format("Error:{0}不存在", IntermediateHHC)); } } else { Console.WriteLine(string.Format("Error:{0}不存在", IntermediateHHP)); } return false; } private void ChangeFileToAnsi(string inputPath, Encoding sourceEncoding, Encoding destEncoding) { var text = File.ReadAllText(inputPath, sourceEncoding); byte[] bytes = sourceEncoding.GetBytes(text); // convert to win bytes var destBytes = Encoding.Convert( sourceEncoding, destEncoding, bytes); File.WriteAllBytes(inputPath, destBytes); } private void ReplaceFileText(string inputPath, string sourceText, string destText, Encoding encoding) { var text = File.ReadAllText(inputPath, Encoding.UTF8); text = text.Replace(sourceText, destText); File.WriteAllText(inputPath, text, encoding); } static void StartProc(string application, string command) { Debug.Assert(File.Exists(application)); var process = new Process { StartInfo = new ProcessStartInfo { FileName = application, Arguments = " " + command, RedirectStandardOutput = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, StandardOutputEncoding = Encoding.UTF8 } }; process.Start(); while (!process.StandardOutput.EndOfStream) { string line = process.StandardOutput.ReadLine(); Console.WriteLine(line); // Debug.WriteLine(line); } process.WaitForExit(); } } }
另外为了确保目标机器没有安装doxygen或者hhc都不影响我生成文档,因此我将这些执行档都复制了一份放到了doxygen项目下,代码中的一些额外步骤就是强行将原始project文件中的hhc路径改成当前目录下的hhc。
目录结构如下: