OpenCC 是一個開源的中文繁簡轉換工具,可以用來將簡體中文轉換成繁體中文,或是將繁體中文轉換成簡體中文,我已經用十多年了,是個很棒的工具。不過,我以前一直都是在 Linux 底下使用它,因為官方並沒有提供 Windows 執行檔,如果要能在 Windows 直接執行,就需要自行編譯原始碼才行。這篇文章將介紹如何在 Windows 平台上建置 OpenCC 專案,以及分享如何透過 .NET 8 (C#
) 載入 opencc.dll
直接呼叫 C++ 的函式庫。
安裝 Microsoft Visual C++ Redistributable
由於 OpenCC 主要以 C++ 開發而成,所以在 Windows 平台上執行時,需要安裝 Microsoft Visual C++ Redistributable 才能確保執行時不會遇到缺少 DLL 的問題。
你可以直接到 Microsoft Visual C++ Redistributable latest supported downloads 頁面下載 X64
版本回來安裝即可:
直接下載連結: https://aka.ms/vs/17/release/vc_redist.x64.exe
安裝 CMake 建置工具
CMake 是一套強大的軟體建置系統,主要用來建置 C++ 的程式碼,而 OpenCC 若要在 Windows 平台建置,就要使用 CMake 來建置專案。
我打算使用 Chocolatey 來安裝 CMake 3.29.1 套件:
choco install cmake --installargs 'ADD_CMAKE_TO_PATH=User' --apply-install-arguments-to-dependencies
下載原始碼並建置專案
請使用「命令提示字元」(Command Prompt) 來執行以下指令:
-
下載最新版原始碼
git clone https://github.com/BYVoid/OpenCC.git
cd OpenCC
-
建立 build/
資料夾
這個步驟會指定最後的安裝路徑在 C:\Tools\OpenCC
目錄下,執行完後會產生一個 build/
資料夾,裡面會準備好編譯的原始碼:
cmake -S. -Bbuild -DCMAKE_INSTALL_PREFIX:PATH="C:\Tools\OpenCC"
在建置成功後,你就會在 build/
資料夾下看到完整的 Visual Studio 方案檔 (opencc.sln
),也代表你可以用 Visual Studio 2022 來開啟並編譯這個方案。
你從 cmake 的文件中可以發現,當你加上 -D
參數時,若設定選項的值是個「路徑」的話,你可以加上 :PATH
代表你要設定的是一個「路徑」,如果輸入相對路徑的話,cmake
在執行時會自動幫你轉成「絕對路徑」。
-
建置專案並安裝至指定路徑
接下來可以直接透過 cmake
命令進行建置並自動安裝,你若使用 Visual Studio 開啟 build\opencc.sln
也可以建置!
cmake --build build --config Release --target install
這個命令的 --target install
參數,代表在建置成功後,會自動安裝到指定目錄。
-
最後一個步驟,則是自行設定 PATH
環境變數,讓系統可以自動找到 opencc.exe
執行檔:
以我上述的安裝步驟來說,你要設定的路徑在:
C:\Tools\OpenCC\bin
請注意: 由於在建置 OpenCC 的時候,我們已經設定了 CMAKE_INSTALL_PREFIX
為 C:\Tools\OpenCC
,所以 opencc.exe
會被安裝在 C:\Tools\OpenCC\bin
目錄下,如果你今後移動了 opencc.exe
執行檔的路徑,他在執行時還是會去找 C:\Tools\OpenCC
目錄下的相關檔案,路徑是寫死在程式中的。也因為這樣,如果你想要變更路徑,就需要自行重新編譯程式,並指定不同的 CMAKE_INSTALL_PREFIX
參數值。
使用 OpenCC 命令
在安裝完成後,你可以在命令提示字元中輸入 opencc
來執行 OpenCC 的命令列工具,以下是一些常見用法:
-
查看版本
opencc --version
Open Chinese Convert (OpenCC) Command Line Tool
Version: 1.1.7
-
查看使用說明
opencc -h
Open Chinese Convert (OpenCC) Command Line Tool
Author: Carbo Kuo <byvoid@byvoid.com>
Bug Report: http://github.com/BYVoid/OpenCC/issues
Usage:
opencc [--noflush <bool>] [-i <file>] [-o <file>] [-c <file>] [--]
[--version] [-h]
Options:
--noflush <bool>
Disable flush for every line
-i <file>, --input <file>
Read original text from <file>.
-o <file>, --output <file>
Write converted text to <file>.
-c <file>, --config <file>
Configuration file
--, --ignore_rest
Ignores the rest of the labeled arguments following this flag.
--version
Displays version information and exits.
-h, --help
Displays usage information and exits.
Open Chinese Convert (OpenCC) Command Line Tool
-
將 README_CN.md
(簡體中文) 轉換為 README_TW.txt
(繁體中文)
若要將一份簡體中文的 README_CN.md
轉換為繁體中文的 README_TW.md
,以下是我常用的指令:
opencc -i README_CN.md -o README_TW.md -c s2twp.json
你可以從 C:\Tools\OpenCC\share\opencc
目錄下找到許多不同的轉換設定檔 (*.json
),這裡我使用的是 s2twp.json
,代表將簡體中文轉換為繁體中文(台灣)。這裡的 s
代表簡體中文,t
代表繁體中文,w
代表台灣慣用字,而 p
(phrase) 才是代表台灣慣用詞彙。
執行 OpenCC 的效能測試
OpenCC 的執行效率非常高,如果要看看繁簡轉換的效能,必須重新編譯程式,並加入 ENABLE_BENCHMARK=ON
參數。
-
準備 OpenCC 的效能測試
cmake -S. -Bbuild -DENABLE_BENCHMARK=ON -DCMAKE_INSTALL_PREFIX:PATH=C:\Tools\OpenCC
-
建置專案
cmake --build build --config Release
-
手動複製 benchmark.dll
檔案到發行目錄
copy build\src\benchmark\benchmark.dll build\src\benchmark\Release\
-
執行效能測試
build\src\benchmark\Release\performance.exe
從 C# 呼叫 OpenCC 執行
這裡我參考了黑暗執行緒的使用 C# 整合 OpenCC 執行中文繁簡轉換文章中提供的範例,並修正了一些 Interop
寫法 (主要是用來避免記憶體洩漏的問題)。也参考了 Opencc Memory Leak 文章,改用 OpenCC 內部原生的 opencc_convert_utf8_free
與 opencc_close
方法來釋放記憶體,這才徹底解決了記憶體洩漏的問題。新版如下:
using System.Runtime.InteropServices;
using System.Text;
public static class OpenCCHelper
{
[DllImport(@"C:\Tools\opencc\bin\opencc.dll", EntryPoint = "opencc_open")]
private static extern IntPtr opencc_open(string configFileName);
[DllImport(@"C:\Tools\opencc\bin\opencc.dll", EntryPoint = "opencc_convert_utf8")]
private static extern IntPtr opencc_convert_utf8(IntPtr opencc, IntPtr input, UIntPtr length);
[DllImport(@"C:\Tools\opencc\bin\opencc.dll", EntryPoint = "opencc_convert_utf8_free")]
private static extern IntPtr opencc_convert_utf8_free(IntPtr str);
[DllImport(@"C:\Tools\opencc\bin\opencc.dll", EntryPoint = "opencc_close")]
private static extern IntPtr opencc_close(IntPtr opencc);
public static string ConvertFromSimplifiedToTraditional(this string text, string config = "s2t")
{
return OpenCC(text, config: config);
}
public static string ConvertFromSimplifiedToTraditionalTaiwan(this string text, string config = "s2twp")
{
return OpenCC(text, config: config);
}
public static string ConvertFromTraditionalTaiwanToSimplified(this string text, string config = "tw2sp")
{
return OpenCC(text, config: config);
}
public static string ConvertFromTraditionalToSimplified(this string text, string config = "t2s")
{
return OpenCC(text, config: config);
}
public static string OpenCC(this string text, string config)
{
var configFile = $"C:\\Tools\\OpenCC\\share\\opencc\\{config}.json";
if (!File.Exists(configFile))
{
throw new FileNotFoundException("設定檔找不到", configFile);
}
IntPtr opencc = opencc_open(configFile);
try
{
IntPtr inputPtr = Marshal.StringToCoTaskMemUTF8(text);
try
{
var input = text.ToCharArray();
UIntPtr length = new((uint)Encoding.UTF8.GetByteCount(input));
IntPtr resultPtr = opencc_convert_utf8(opencc, inputPtr, length);
try
{
string? result = Marshal.PtrToStringUTF8(resultPtr);
return result!;
}
finally
{
//改為使用Opencc內建的釋放資源函數
opencc_convert_utf8_free(resultPtr);
}
}
finally
{
Marshal.FreeCoTaskMem(inputPtr);
}
}
finally
{
//改為使用Opencc內建的釋放資源函數
opencc_close(opencc);
}
}
}
使用方式如下:
string text = "";
text = "多奇数位创意有限公司";
Console.WriteLine(text.ConvertFromSimplifiedToTraditionalTaiwan());
text = "多奇數位創意有限公司";
Console.WriteLine(text.ConvertFromTraditionalTaiwanToSimplified());
相關連結