- Notifications
You must be signed in to change notification settings - Fork80
🇨🇳Open Chinese Convert is an opensource project for conversion between Traditional Chinese and Simplified Chinese.(java 中文繁简体转换,支持台湾、香港、中文日文转换。)
License
houbb/opencc4j
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Opencc4j 支持中文繁简体转换,考虑到词组级别。
严格区分「一简对多繁」和「一简对多异」。
完全兼容异体字,可以实现动态替换。
严格审校一简对多繁词条,原则为「能分则不合」。
词库和函数库完全分离,可以自由修改、导入、扩展。
兼容 Windows、Linux、Mac 平台。
支持自定义分词、引导类,优雅实现
支持判断单个字(词)是否为简体/繁体
支持返回字符串中简体/繁体的列表信息
支持中国台湾地区和大陆简体繁简体转换
支持中国香港地区和大陆简体繁简体转换
支持日文新字和大陆简体繁简体转换
兼容双字符汉字,【𨦟】【𪡃】等
- OpenCC
OpenCC 的思想非常优秀,做的也特别棒。但是没有特别为 java 提供的工具。
<dependency> <groupId>com.github.houbb</groupId> <artifactId>opencc4j</artifactId> <version>1.14.0</version></dependency>
核心工具列表如下:
| 序号 | 工具类 | 简介 |
|---|---|---|
| 1 | ZhConverterUtil | 基础的繁简体转换 |
| 2 | ZhTwConverterUtil | 中国台湾地区与大陆的繁简体转换 |
| 3 | ZhHkConverterUtil | 中国香港地区与大陆的繁简体转换 |
| 4 | ZhJpConverterUtil | 日文新字与大陆的繁简体转换 |
所有的工具类方法具有相同的方法设计,便于记忆。
核心方法如下:
| 序号 | 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) | 字符串中是否包含中文 |
Stringoriginal ="生命不息,奮鬥不止";Stringresult =ZhConverterUtil.toSimple(original);Assert.assertEquals("生命不息,奋斗不止",result);
Stringoriginal ="生命不息,奋斗不止";Stringresult =ZhConverterUtil.toTraditional(original);Assert.assertEquals("生命不息,奮鬥不止",result);
对单个字符或者词组进行繁简体判断。
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"));
Assert.assertTrue(ZhConverterUtil.containsSimple("奋"));Assert.assertTrue(ZhConverterUtil.containsSimple("奋斗"));Assert.assertTrue(ZhConverterUtil.containsSimple("奋斗2023"));Assert.assertFalse(ZhConverterUtil.containsSimple("編"));Assert.assertFalse(ZhConverterUtil.containsSimple("編號"));
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("编號"));
Assert.assertTrue(ZhConverterUtil.containsTraditional("編"));Assert.assertTrue(ZhConverterUtil.containsTraditional("編號"));Assert.assertTrue(ZhConverterUtil.containsTraditional("編號2023"));Assert.assertFalse(ZhConverterUtil.containsTraditional("号"));Assert.assertFalse(ZhConverterUtil.containsTraditional("编号"));
返回字符串中繁简体对应的词、字列表,默认支持中文分词。
繁简体列表返回的词组和分词策略紧密相关。
finalStringoriginal ="生命不息奋斗不止";finalList<String>resultList =ZhConverterUtil.simpleList(original);Assert.assertEquals("[生, 命, 不, 息, 奋斗, 不, 止]",resultList.toString());
PS: 很多字是同体字。
finalStringoriginal ="生命不息奮鬥不止";finalList<String>resultList =ZhConverterUtil.traditionalList(original);Assert.assertEquals("[生, 命, 不, 息, 奮, 鬥, 不, 止]",resultList.toString());
Assert.assertEquals("[幹, 乾, 干]",ZhConverterUtil.toTraditional('干').toString());Assert.assertEquals("[發, 髮]",ZhConverterUtil.toTraditional('发').toString());
Assert.assertEquals("[测]",ZhConverterUtil.toSimple('測').toString());
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));
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 保持一致。
简体到繁体:
Stringoriginal ="使用互联网";Stringresult =ZhTwConverterUtil.toTraditional(original);Assert.assertEquals("使用網際網路",result);
繁体到简体:
Stringoriginal ="使用網際網路";Stringresult =ZhTwConverterUtil.toSimple(original);Assert.assertEquals("使用互联网",result);
v1.12.0 版本支持。
为保证方法的一致性,引入ZhHkConverterUtil 工具类,支持方法和ZhConverterUtil 保持一致。
/** * 大陆简体==>香港正體 * @since 1.12.0 */@TestpublicvoidtestHkTraditional() {Stringoriginal ="千家万户瞳瞳日 总把新桃换旧符";Stringresult =ZhHkConverterUtil.toTraditional(original);Assert.assertEquals("千家萬户瞳瞳日 總把新桃換舊符",result);}/** * 香港正體==>大陆简体 */@TestpublicvoidtestHkSimple() {Stringoriginal ="千家萬户瞳瞳日 總把新桃換舊符";Stringresult =ZhHkConverterUtil.toSimple(original);Assert.assertEquals("千家万户瞳瞳日 总把新桃换旧符",result);}
v1.13.0 版本支持。
为保证方法的一致性,引入ZhJpConverterUtil 工具类,支持方法和ZhConverterUtil 保持一致。
实际流程:简体==》标准繁体==》日文新字
/** * 大陆简体==>标准繁体=》日文 */@TestpublicvoidtestJpTraditional() {Stringoriginal ="我在日本学习音乐,并学习了龙的字。";Stringresult =ZhJpConverterUtil.toTraditional(original);Assert.assertEquals("我在日本学習音楽,並学習了竜的字。",result);}/** * 日文=>标准繁体=>简体 */@TestpublicvoidtestJpSimple() {Stringoriginal ="我在日本学習音楽,並学習了竜的字。";Stringresult =ZhJpConverterUtil.toSimple(original);Assert.assertEquals("我在日本学习音乐,并学习了龙的字。",result);}
主要的可配置项包含了分词和数据集合。
二者都是可以配置,并且支持自定义的。
默认工具类等价于如下:
ZhConvertBootstrap.newInstance() .segment(Segments.defaults()) .dataMap(DataMaps.defaults()).init();
中国台湾地区配置等价于:
ZhConvertBootstrap.newInstance() .segment(Segments.twFastForward()) .dataMap(DataMaps.taiwan()).init();
你可以通过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
- 接口内容
publicinterfaceSegment {/** * 分词 * @param original 原始信息 * @return 分词后的列表 */List<String>seg(finalStringoriginal);}
/** * 一个最简单的分词实现。 * 注意:仅仅做演示,不可实际使用。 */publicclassFooSegmentimplementsSegment {@OverridepublicList<String>seg(Stringoriginal) {returnArrays.asList(original,"测试"); }}
我们自定义的分词,直接在默认添加“测试”这样的信息。
finalStringoriginal ="寥落古行宫,宫花寂寞红。白头宫女在,闲坐说玄宗。";finalSegmentsegment =newFooSegment();finalStringresult =ZhConvertBootstrap.newInstance() .segment(segment) .init() .toTraditional(original);Assert.assertEquals("寥落古行宮,宮花寂寞紅。白頭宮女在,閒坐說玄宗。測試",result);
不同的地区,对应的转换规则是不同的。
具体参考一下台湾地区的使用方式即可。
IDataMap 的接口如下。
/** * 数据 map 接口 * @author binbin.hou * @since 1.5.2 */publicinterfaceIDataMap {/** * 繁体=》简体 词组 * @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: 后续考虑引入更加简单的实现方式,比如基于文本拓展,不过可扩展性没有接口灵活。
用于用户参考,可以自定义实现自己的实现,更加符合实际业务。
v1.9.0 开始支持,方便用户拓展。
比如首先自定义一个 dataMap 类,集成 AbstractDataMapExtra 可以在指定的 IDataMap 基础上额外指定词组等信息。
publicclassMyFooDataMapExtraextendsAbstractDataMapExtra {publicMyFooDataMapExtra(IDataMapbaseDataMap) {super(baseDataMap); }// 默认在基本的繁简体基础上拓展publicMyFooDataMapExtra() {this(DataMaps.defaults()); }privateMap<String,List<String>>of(Stringkey,List<String>list) {Map<String,List<String>>map =newHashMap<>();map.put(key,list);returnmap; }@OverrideprotectedMap<String,List<String>>tsPhraseExtra() {// 估计写了个错的,用来演示returnof("風玥",Arrays.asList("风月")); }@OverrideprotectedMap<String,List<String>>tsCharExtra() {returnnull; }@OverrideprotectedMap<String,List<String>>stPhraseExtra() {// 估计写了个错的returnof("风月",Arrays.asList("風玥")); }@OverrideprotectedMap<String,List<String>>stCharExtra() {returnnull; }}
我们只需要在引导类 ZhConvertBootstrap 指定我们的 dataMap 和对应的分词策略,即可。
// 1.1自定义的额外数据集finalIDataMapdataMap =newMyFooDataMapExtra();// 1.2 指定分词策略finalSegmentsegment =newDataMapFastForwardSegment(dataMap);// 2. 指定ZhConvertBootstrapbs =ZhConvertBootstrap.newInstance() .dataMap(dataMap) .segment(segment) .init() ;// 3. 使用Assert.assertEquals(bs.toTraditional("人生自是有情痴,此恨不关风月"),"人生自是有情癡,此恨不關風玥");Assert.assertEquals(bs.toSimple("人生自是有情癡,此恨不關風玥"),"人生自是有情痴,此恨不关风月");
V1.11.0 版本支持。
有时候我们需要判断一个字符串是否为繁简体,isSimple()、isTraditional() 默认要求全部匹配,无法满足全部场景。
这里允许用户自定义相关的策略。
内置策略见ZhMatches 工具方法。
| 策略 | 说明 | 备注 |
|---|---|---|
| simpleAll() | 满足全部简体 | isSimple 判断时,默认策略 |
| simpleAny() | 满足任一简体 | - |
| simpleOverHalf() | 满足超过一半简体 | - |
| traditionalAll() | 满足全部繁体 | isTraditional 判断时,默认策略 |
| traditionalAny() | 满足任一繁体 | - |
| traditionalOverHalf() | 满足超过一半繁体 | - |
// 全部ZhConvertBootstrapbs =ZhConvertBootstrap.newInstance() .isSimpleMatch(ZhMatches.simpleAll()) .init();Stringtext ="123我456";Assert.assertFalse(bs.isSimple(text));// 任一bs.isSimpleMatch(ZhMatches.simpleAny()).init();Assert.assertTrue(bs.isSimple(text));
// 全部ZhConvertBootstrapbs =ZhConvertBootstrap.newInstance() .isTraditionalMatch(ZhMatches.traditionalAll()) .init();Stringtext ="123俺們456";Assert.assertFalse(bs.isTraditional(text));// 任一bs.isTraditionalMatch(ZhMatches.traditionalAny()).init();Assert.assertTrue(bs.isTraditional(text));;
如果系统内置的策略不满足,你可以自定义。
实现 ZhMatch 接口,引导类中指定即可使用。
OpenCC 提供的原始数据信息。
jieba-analysis 提供中文分词
需求和 BUG 在这里,欢迎提供宝贵的建议。
如果对您有帮助,欢迎 Star 鼓励作者。
数据字典插件化
考虑长文本分段,并行转换
About
🇨🇳Open Chinese Convert is an opensource project for conversion between Traditional Chinese and Simplified Chinese.(java 中文繁简体转换,支持台湾、香港、中文日文转换。)
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.