使用Jortho实现拼写检查

码云
2020-12-03 08:54

本文主要介绍Jortho实现拼写检查,具体的实现代码如下:

因为Jortho本身提供了一个SwingUI的方式实现拼写检查,一些方法并没有直接暴露,下面的代码中使用反射修改了方法的可访问性。

package com.findsrc.tool.service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.inet.jortho.LanguageBundle;
import com.inet.jortho.SpellChecker;


public class JorthoSpellCheckService implements SpellCheckService {

	private static final Log log = LogFactory.getLog(JazzySpellCheckService.class);

    //反射的方法
	private static final Map<String, Method> methods = new HashMap<>();
    //字典对象
	private Object dictionary;
    //语言包
	private LanguageBundle bundle;

	public JorthoSpellCheckService() {
		try {
			this.init(); //初始化,包含反射
		} catch (Throwable t) {
			log.error("字典初始化错误", t);
		}
	}

    /**
    *检查方法,返回拼写错误的单词
    *@param str 需要检查的语句
    */
	@Override
	public Set<String> doCheck(String str) {
		Set<String> errors = new HashSet<>();
		String[] words = str.split("[\\s,;\\.-]+", 0); //分词
		boolean newSentence = true;
		for (String word : words) {
			boolean b = true;
			boolean nextNewSentence = false;
			if (word.length() > 1) {
				if ('.' == word.charAt(word.length() - 1)) {
					nextNewSentence = true;
					word = word.substring(0, word.length() - 1);
				}
				try {
                    //检查单词是不是拼写错误
					b = (Boolean) invokeMethod(LanguageBundle.class, "existInDictionary", bundle, word, dictionary, SpellChecker.getOptions(),
							newSentence);
				} catch (Throwable t) {
					// 默认存在
				}
			}
			if (!b) {
				errors.add(word);
			}
			newSentence = nextNewSentence;
		}
		return errors;
	}

	private void init() throws Throwable {
        //设置配置文件目录
        SpellChecker.registerDictionaries(JorthoSpellCheckService.class.getResource("/dict/"), "en");
        //忽略大小写
		SpellChecker.getOptions().setCaseSensitive(false);
        //反射修改方法的可访问性
		setAccessibleMethod(LanguageBundle.class, "get", Locale.class);
		setAccessibleMethod(LanguageBundle.class, "existInDictionary", String.class,
				JorthoSpellCheckService.class.getClassLoader().loadClass("com.inet.jortho.Dictionary"), com.inet.jortho.SpellCheckerOptions.class,
				boolean.class);
		setAccessibleMethod(SpellChecker.class, "getCurrentDictionary");

		while (SpellChecker.getCurrentLocale() == null) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
			}
		}
		dictionary = invokeMethod(SpellChecker.class, "getCurrentDictionary", null);
		bundle = (LanguageBundle) invokeMethod(LanguageBundle.class, "get", null, SpellChecker.getCurrentLocale());
	}

    //反射修改方法的可访问性
	private static void setAccessibleMethod(Class<?> cls, String name, Class<?>... parameterTypes) throws NoSuchMethodException {
		Method method = cls.getDeclaredMethod(name, parameterTypes);
		method.setAccessible(true);
		methods.put(cls.getName() + "." + name, method);
	}

    //反射执行方法
	private static Object invokeMethod(Class<?> cls, String name, Object obj, Object... args)
			throws InvocationTargetException, IllegalAccessException {
		return methods.get(cls.getName() + "." + name).invoke(obj, args);
	}
}

 

需要用到的配置文件:

dict/dictionaries.cnf (字典配置)

extension=.ortho
languages=de,en,it,fr,es,ru

dict/dictionary_en.ortho (英文字典)

可以自行去下载,这里不方便贴出来展示。

 

如果要支持中文的拼写检查,需要调整几个地方:

1)下载中文字典文件

2)修改分词方式(英文分词使用了空格、标点符号分隔)

3)修改字典配置,增加中文支持

 

总体说来Jortho的拼写检查还可以,但不如另外一个Jazzy的效果好,下篇文章会介绍如何使用Jazzy实现拼写检查。

全部评论

相关文章