Opencc4j
Opencc4j 支援中文繁簡體轉換,考慮到片語級別。
線上體驗
Features 特點
- 嚴格區分「一簡對多繁」和「一簡對多異」。
- 完全相容異體字,可以實現動態替換。
- 嚴格審校一簡對多繁詞條,原則為「能分則不合」。
- 詞庫和函式庫完全分離,可以自由修改、匯入、擴充套件。
- 相容 Windows、Linux、Mac 平臺。
- 支援自定義分詞
- 支援判斷單個字(詞)是否為簡體/繁體
- 支援返回字串中簡體/繁體的列表資訊
- 支援臺灣地區繁簡體轉換
v1.8.0 版本變更
- 豐富工具類方法
- 最佳化繁簡體判斷邏輯
變更日誌
創作緣由
- OpenCC
OpenCC 的思想非常優秀,做的也特別棒。但是沒有特別為 java 提供的工具。
- jopencc
jopencc 沒有提供分詞功能。
快速開始
maven 引入
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>opencc4j</artifactId>
<version>1.8.0</version>
</dependency>
api 概覽
核心工具列表如下:
序號 | 工具類 | 簡介 |
---|---|---|
1 | ZhConverterUtil | 基礎的繁簡體轉換 |
2 | ZhTwConverterUtil | 臺灣地區的繁簡體轉換 |
所有的工具類方法具有相同的方法設計,便於記憶。
核心方法如下:
序號 | api 方法 | 簡介 |
---|---|---|
1 | toSimple(String) | 轉為簡體 |
2 | toTraditional(String) | 轉為繁體 |
3 | simpleList(String) | 返回包含的簡體列表 |
4 | traditionalList(String) | 返回包含的繁體列表 |
5 | toSimple(char) | 返回單個漢字對應的所有簡體字列表 |
6 | toTraditional(char) | 返回單個漢字對應的所有繁體字列表 |
7 | isSimple(String) | 是否全部為簡體 |
8 | isSimple(char) | 單個字元是否為簡體 |
9 | containsSimple(String) | 字元中是否為包含簡體 |
10 | isTraditional(String) | 是否全部為繁體 |
11 | isTraditional(char) | 單個字元是否為繁體 |
12 | containsTraditional(String) | 字元中是否為包含繁體 |
13 | isChinese(String) | 是否全部為中文 |
14 | isChinese(char) | 單個字元是否為中文 |
15 | containsChinese(char) | 字串中是否包含中文 |
繁簡體轉換
轉為簡體 toSimple
String original = "生命不息,奮鬥不止";
String result = ZhConverterUtil.toSimple(original);
Assert.assertEquals("生命不息,奮鬥不止", result);
轉為繁體 toTraditional
String original = "生命不息,奮鬥不止";
String result = ZhConverterUtil.toTraditional(original);
Assert.assertEquals("生命不息,奮鬥不止", result);
繁簡體判斷
對單個字元或者片語進行繁簡體判斷。
是否為簡體 isSimple
Assert.assertTrue(ZhConverterUtil.isSimple('奮'));
Assert.assertTrue(ZhConverterUtil.isSimple("奮"));
Assert.assertTrue(ZhConverterUtil.isSimple("奮鬥"));
Assert.assertFalse(ZhConverterUtil.isSimple('奮'));
Assert.assertFalse(ZhConverterUtil.isSimple("奮"));
Assert.assertFalse(ZhConverterUtil.isSimple("奮鬥"));
Assert.assertFalse(ZhConverterUtil.isSimple("奮鬥"));
Assert.assertFalse(ZhConverterUtil.isSimple("beef"));
是否包含簡體 containsSimple
Assert.assertTrue(ZhConverterUtil.containsSimple("奮"));
Assert.assertTrue(ZhConverterUtil.containsSimple("奮鬥"));
Assert.assertTrue(ZhConverterUtil.containsSimple("奮鬥2023"));
Assert.assertFalse(ZhConverterUtil.containsSimple("編"));
Assert.assertFalse(ZhConverterUtil.containsSimple("編號"));
是否為繁體 isTraditional
Assert.assertTrue(ZhConverterUtil.isTraditional('編'));
Assert.assertTrue(ZhConverterUtil.isTraditional("編"));
Assert.assertTrue(ZhConverterUtil.isTraditional("編號"));
Assert.assertFalse(ZhConverterUtil.isTraditional('編'));
Assert.assertFalse(ZhConverterUtil.isTraditional("編"));
Assert.assertFalse(ZhConverterUtil.isTraditional("編號"));
Assert.assertFalse(ZhConverterUtil.isTraditional("編號"));
是否包含繁體 containsTraditional
Assert.assertTrue(ZhConverterUtil.containsTraditional("編"));
Assert.assertTrue(ZhConverterUtil.containsTraditional("編號"));
Assert.assertTrue(ZhConverterUtil.containsTraditional("編號2023"));
Assert.assertFalse(ZhConverterUtil.containsTraditional("號"));
Assert.assertFalse(ZhConverterUtil.containsTraditional("編號"));
句子中包含的繁簡體列表返回
返回字串中繁簡體對應的詞、字列表,預設支援中文分詞。
繁簡體列表返回的片語和分詞策略緊密相關。
簡體列表 simpleList
final String original = "生命不息奮鬥不止";
final List<String> resultList = ZhConverterUtil.simpleList(original);
Assert.assertEquals("[生, 命, 不, 息, 奮鬥, 不, 止]", resultList.toString());
繁體列表 traditionalList
PS: 很多字是同體字。
final String original = "生命不息奮鬥不止";
final List<String> resultList = ZhConverterUtil.traditionalList(original);
Assert.assertEquals("[生, 命, 不, 息, 奮, 鬥, 不, 止]", resultList.toString());
單個漢字對應的繁簡體列表
繁體字列表
Assert.assertEquals("[幹, 乾, 幹]", ZhConverterUtil.toTraditional('幹').toString());
Assert.assertEquals("[發, 髮]", ZhConverterUtil.toTraditional('發').toString());
簡體字列表
Assert.assertEquals("[測]", ZhConverterUtil.toSimple('測').toString());
中文工具方法
是否為中文 isChinese
Assert.assertTrue(ZhConverterUtil.isChinese("你"));
Assert.assertTrue(ZhConverterUtil.isChinese("你好"));
Assert.assertTrue(ZhConverterUtil.isChinese('你'));
Assert.assertFalse(ZhConverterUtil.isChinese("你0"));
Assert.assertFalse(ZhConverterUtil.isChinese("10"));
Assert.assertFalse(ZhConverterUtil.isChinese('0'));
Assert.assertFalse(ZhConverterUtil.isChinese(""));
Assert.assertFalse(ZhConverterUtil.isChinese(null));
是否包含中文 containsChinese
Assert.assertTrue(ZhConverterUtil.containsChinese("你"));
Assert.assertTrue(ZhConverterUtil.containsChinese("你好"));
Assert.assertTrue(ZhConverterUtil.containsChinese("你0"));
Assert.assertFalse(ZhConverterUtil.containsChinese("10"));
Assert.assertFalse(ZhConverterUtil.containsChinese(""));
Assert.assertFalse(ZhConverterUtil.containsChinese(null));
臺灣繁簡體轉換
工具類
為保證方法的一致性,引入 ZhTwConverterUtil
工具類,支援方法和 ZhConverterUtil
保持一致。
測試用例
簡體到繁體:
String original = "使用網際網路";
String result = ZhTwConverterUtil.toTraditional(original);
Assert.assertEquals("使用網際網路", result);
繁體到簡體:
String original = "使用網際網路";
String result = ZhTwConverterUtil.toSimple(original);
Assert.assertEquals("使用網際網路", result);
配置引導類
引導類說明
主要的可配置項包含了分詞和資料集合。
二者都是可以配置,並且支援自定的。
預設配置
預設工具類等價於如下:
ZhConvertBootstrap.newInstance()
.segment(Segments.defaults())
.dataMap(DataMaps.defaults());
臺灣地區配置
臺灣地區配置等價於:
ZhConvertBootstrap.newInstance()
.segment(Segments.defaults())
.dataMap(DataMaps.taiwan());
中文分詞策略
系統內建分詞方式
你可以透過 Segments
工具類獲取系統內建的分詞實現。
序號 | 方法 | 準確性 | 效能 | 備註 |
---|---|---|---|---|
1 | defaults() | 高 | 高 | 預設分詞形式,暫時為 fastForward 策略 |
2 | fastForward() | 較高 | 高 | fast-forward 分詞策略 |
3 | chars() | 低 | 高 | 將字串轉換為單個字元列表,一般不建議使用 |
4 | huaBan() | 高 | 一般 | 花瓣的結巴分詞策略 |
花瓣結巴分詞
花瓣結巴分詞在使用時,需要自行引入結巴分詞依賴。
<dependency>
<groupId>com.huaban</groupId>
<artifactId>jieba-analysis</artifactId>
<version>1.0.2</version>
</dependency>
自定義
你有時候可能除了上述的兩種分詞方式,會有更加適合自己業務的分詞實現。
Opencc4j 支援自定義分詞實現,只需要實現分詞介面 Segment
- 介面內容
public interface Segment {
/**
* 分詞
* @param original 原始資訊
* @return 分詞後的列表
*/
List<String> seg(final String original);
}
測試程式碼
自定義分詞實現類
/**
* 一個最簡單的分詞實現。
* 注意:僅僅做演示,不可實際使用。
*/
public class FooSegment implements Segment {
@Override
public List<String> seg(String original) {
return Arrays.asList(original, "測試");
}
}
分詞測試
我們自定義的分詞,直接在預設新增“測試”這樣的資訊。
final String original = "寥落古行宮,宮花寂寞紅。白頭宮女在,閒坐說玄宗。";
final Segment segment = new FooSegment();
final String result = ZhConvertBootstrap.newInstance()
.segment(segment)
.toTraditional(original);
Assert.assertEquals("寥落古行宮,宮花寂寞紅。白頭宮女在,閒坐說玄宗。測試", result);
資料介面自定義
不同的地區,對應的轉換規則是不同的。
具體參考一下臺灣地區的使用方式即可。
介面說明
IDataMap 的介面如下。
/**
* 資料 map 介面
* @author binbin.hou
* @since 1.5.2
*/
public interface IDataMap {
/**
* 繁體=》簡體 片語
* @return 結果
* @since 1.5.2
*/
Map<String, List<String>> tsPhrase();
/**
* 繁體=》簡體 單個字
* @return 結果
* @since 1.5.2
*/
Map<String, List<String>> tsChar();
/**
* 簡體=》繁體 片語
* @return 結果
* @since 1.5.2
*/
Map<String, List<String>> stPhrase();
/**
* 簡體=》繁體 單個字
* @return 結果
* @since 1.5.2
*/
Map<String, List<String>> stChar();
/**
* 繁體字所有字元
* @return 繁體字所有字元
* @since 1.6.2
*/
Set<String> tChars();
/**
* 簡體字所有字元
* @return 繁體字所有字元
* @since 1.8.0
*/
Set<String> sChars();
}
自定義說明
如果需要擴充對應的資料,建議繼承原始的實現,然後新增額外的資料資訊即可。
可以參考 臺灣地區實現
ps: 後續考慮引入更加簡單的實現方式,比如基於文字擴充,不過可擴充套件性沒有介面靈活。
技術鳴謝
OpenCC
OpenCC 提供的原始資料資訊。
花瓣
jieba-analysis 提供中文分詞
Issues & Bugs
需求和 BUG 在這裡,歡迎提供寶貴的建議。
如果對您有幫助,歡迎 Star 鼓勵作者。
NLP 開源矩陣
後期 Road-Map
- [ ] 資料字典外掛化
- [ ] 考慮長文字分段,並行轉換