我正在为作者移植一个应用程序到UWP平台。我剩下的唯一一块拼图是NHunspell库。我广泛地使用它进行拼写检查和词库功能。我已经对它进行了定制,并为各种事情创建了定制词典(即每个写作项目都有不同的字典)。这个图书馆是个漂亮的东西。
但是,我似乎不能在我的UWP应用程序中包括这个DLL。
1)是否有强制使用这个DLL的方法?我真的很喜欢NHunSpell系统的设置。这是常识,而且非常快速和容易使用。
2)如果没有,是否有人能为定制字典、定制拼写检查等推荐更好的解决方案?
更新3
经过大量的更新和在线阅读,我发现了一个关于拼写检查理论的链接。下面是一个简单的例子(我用得最多)。
http://www.anotherchris.net/csharp/how-to-write-a-spelling-corrector-in-csharp/
在阅读了本文,获取了基本代码,并从Hun拼写.dic文件中删除了英语单词之后,我创建了自己的拼写检查库,该库在UWP中工作。
一旦我把它固化,我将把它作为下面的一个答案,捐赠给SO社区。:)
更新2
我承认使用亨斯韦。看起来根本不可能.有没有其他的库/包,任何人都可以建议?
更新:
我可能需要重新定义不能包含DLL的语句:我不能通过NuGet包含DLL。它抱怨DLL与UAP/UWP平台不兼容。
我能够通过链接到现有的动态链接库(而不是)手动地将DLL包括在我的项目中。但是,该DLL确实与UAP平台不兼容。对拼写检查单词的简单调用在WinForms中运行良好,但会立即与System.IO.FileNotFoundException崩溃。
NHunspell的构造函数确实可以加载相关的.dic和.aff文件。但是,我已经通过将文件加载到内存中,然后调用备用构造函数来缓解这种情况,该构造函数为每个文件取一个字节数组,而不是一个文件名。它仍然崩溃,但有一个新的Method not found错误:
String System.AppDomain.get_RelativeSearchPath()
我正在寻找任何拼写检查引擎,将在UAP框架内工作。出于熟悉的原因,我更希望它是NHunspell。然而,我并不是对这样一个事实视而不见--作为一种选择,这种可能性越来越小。
和我一起工作的人建议我使用内置拼写检查选项。但是,我不能使用内置的Windows 10/TextBox拼写检查功能(据我所知),因为我无法控制自定义字典,也不能禁用诸如自动大写和单词替换之类的功能(如果它认为这个词接近正确的猜测,它就会替换它)。那些东西对作家来说是一章自杀!作者可以在操作系统级别上关闭它们,但他们可能希望将其用于其他应用程序,而不是这个应用程序。
请让我知道,如果有一个解决方案的NHunspell.如果你不知道一个工作,请让我知道你最好的替换自定义拼写检查引擎,在UAP框架内工作。
另外,我还使用NHunspell作为其词库功能。它在我的windows应用程序中运行得很好。我也必须替换这个功能--希望与拼写检查引擎相同。然而,如果你知道一个好的辞典引擎(但它不拼写检查),这也是好的!
谢谢你!!
发布于 2016-03-20 16:22:32
我下载了NHunspell库的源代码,并试图构建一个支持UWP的库,但是我发现了编组NHunspell的问题。
这个包装载了只在x86和x64架构下工作的dll,因此在arm (移动电话、平板电脑)中,应用程序将无法工作。
该包用系统调用加载dll:
[DllImport("kernel32.dll")]
internal static extern IntPtr LoadLibrary(string fileName);我认为在UWP中工作需要重写,因为UWP使用的是沙箱。
国际水文学组织只有两个选择:
1)在UWP的限制下重写编组类。
2)不要在你的程序中使用饥饿咒语。
我对UWP的dll不太了解,但我相信重写可能会非常困难。
发布于 2016-03-25 14:17:23
正如我所承诺的,这是我为做拼写检查而建的课程。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Com.HanelDev.HSpell
{
public class HSpellProcess
{
private Dictionary<string, string> _dictionary = new Dictionary<string, string>();
public int MaxSuggestionResponses { get; set; }
public HSpellProcess()
{
MaxSuggestionResponses = 10;
}
public void AddToDictionary(string w)
{
if (!_dictionary.ContainsKey(w.ToLower()))
{
_dictionary.Add(w.ToLower(), w);
}
else
{
// Upper case words are more specific (but may be the first word
// in a sentence.) Lower case words are more generic.
// If you put an upper-case word in the dictionary, then for
// it to be "correct" it must match case. This is not true
// for lower-case words.
// We want to only replace existing words with their more
// generic versions, not the other way around.
if (_dictionary[w.ToLower()].CaseSensitive())
{
_dictionary[w.ToLower()] = w;
}
}
}
public void LoadDictionary(byte[] dictionaryFile, bool resetDictionary = false)
{
if (resetDictionary)
{
_dictionary = new Dictionary<string, string>();
}
using (MemoryStream ms = new MemoryStream(dictionaryFile))
{
using (StreamReader sr = new StreamReader(ms))
{
string tmp = sr.ReadToEnd();
tmp = tmp.Replace("\r\n", "\r").Replace("\n", "\r");
string [] fileData = tmp.Split("\r".ToCharArray());
foreach (string line in fileData)
{
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
{
continue;
}
string word = line;
// I added all of this for file imports (not array imports)
// to be able to handle words from Hunspell dictionaries.
// I don't get the hunspell derivatives, but at least I get
// the root word.
if (line.Contains("/"))
{
string[] arr = line.Split("/".ToCharArray());
word = arr[0];
}
AddToDictionary(word);
}
}
}
}
public void LoadDictionary(Stream dictionaryFileStream, bool resetDictionary = false)
{
string s = "";
using (StreamReader sr = new StreamReader(dictionaryFileStream))
{
s = sr.ReadToEnd();
}
byte [] bytes = Encoding.UTF8.GetBytes(s);
LoadDictionary(bytes, resetDictionary);
}
public void LoadDictionary(List<string> words, bool resetDictionary = false)
{
if (resetDictionary)
{
_dictionary = new Dictionary<string, string>();
}
foreach (string line in words)
{
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
{
continue;
}
AddToDictionary(line);
}
}
public string ExportDictionary()
{
StringBuilder sb = new StringBuilder();
foreach (string k in _dictionary.Keys)
{
sb.AppendLine(_dictionary[k]);
}
return sb.ToString();
}
public HSpellCorrections Correct(string word)
{
HSpellCorrections ret = new HSpellCorrections();
ret.Word = word;
if (_dictionary.ContainsKey(word.ToLower()))
{
string testWord = word;
string dictWord = _dictionary[word.ToLower()];
if (!dictWord.CaseSensitive())
{
testWord = testWord.ToLower();
dictWord = dictWord.ToLower();
}
if (testWord == dictWord)
{
ret.SpelledCorrectly = true;
return ret;
}
}
// At this point, we know the word is assumed to be spelled incorrectly.
// Go get word candidates.
ret.SpelledCorrectly = false;
Dictionary<string, HSpellWord> candidates = new Dictionary<string, HSpellWord>();
List<string> edits = Edits(word);
GetCandidates(candidates, edits);
if (candidates.Count > 0)
{
return BuildCandidates(ret, candidates);
}
// If we didn't find any candidates by the main word, look for second-level candidates based on the original edits.
foreach (string item in edits)
{
List<string> round2Edits = Edits(item);
GetCandidates(candidates, round2Edits);
}
if (candidates.Count > 0)
{
return BuildCandidates(ret, candidates);
}
return ret;
}
private void GetCandidates(Dictionary<string, HSpellWord> candidates, List<string> edits)
{
foreach (string wordVariation in edits)
{
if (_dictionary.ContainsKey(wordVariation.ToLower()) &&
!candidates.ContainsKey(wordVariation.ToLower()))
{
HSpellWord suggestion = new HSpellWord(_dictionary[wordVariation.ToLower()]);
suggestion.RelativeMatch = RelativeMatch.Compute(wordVariation, suggestion.Word);
candidates.Add(wordVariation.ToLower(), suggestion);
}
}
}
private HSpellCorrections BuildCandidates(HSpellCorrections ret, Dictionary<string, HSpellWord> candidates)
{
var suggestions = candidates.OrderByDescending(c => c.Value.RelativeMatch);
int x = 0;
ret.Suggestions.Clear();
foreach (var suggest in suggestions)
{
x++;
ret.Suggestions.Add(suggest.Value.Word);
// only suggest the first X words.
if (x >= MaxSuggestionResponses)
{
break;
}
}
return ret;
}
private List<string> Edits(string word)
{
var splits = new List<Tuple<string, string>>();
var transposes = new List<string>();
var deletes = new List<string>();
var replaces = new List<string>();
var inserts = new List<string>();
// Splits
for (int i = 0; i < word.Length; i++)
{
var tuple = new Tuple<string, string>(word.Substring(0, i), word.Substring(i));
splits.Add(tuple);
}
// Deletes
for (int i = 0; i < splits.Count; i++)
{
string a = splits[i].Item1;
string b = splits[i].Item2;
if (!string.IsNullOrEmpty(b))
{
deletes.Add(a + b.Substring(1));
}
}
// Transposes
for (int i = 0; i < splits.Count; i++)
{
string a = splits[i].Item1;
string b = splits[i].Item2;
if (b.Length > 1)
{
transposes.Add(a + b[1] + b[0] + b.Substring(2));
}
}
// Replaces
for (int i = 0; i < splits.Count; i++)
{
string a = splits[i].Item1;
string b = splits[i].Item2;
if (!string.IsNullOrEmpty(b))
{
for (char c = 'a'; c <= 'z'; c++)
{
replaces.Add(a + c + b.Substring(1));
}
}
}
// Inserts
for (int i = 0; i < splits.Count; i++)
{
string a = splits[i].Item1;
string b = splits[i].Item2;
for (char c = 'a'; c <= 'z'; c++)
{
inserts.Add(a + c + b);
}
}
return deletes.Union(transposes).Union(replaces).Union(inserts).ToList();
}
public HSpellCorrections CorrectFrom(string txt, int idx)
{
if (idx >= txt.Length)
{
return null;
}
// Find the next incorrect word.
string substr = txt.Substring(idx);
int idx2 = idx;
List<string> str = substr.Split(StringExtensions.WordDelimiters).ToList();
foreach (string word in str)
{
string tmpWord = word;
if (string.IsNullOrEmpty(word))
{
idx2++;
continue;
}
// If we have possessive version of things, strip the 's off before testing
// the word. THis will solve issues like "My [mother's] favorite ring."
if (tmpWord.EndsWith("'s"))
{
tmpWord = word.Substring(0, tmpWord.Length - 2);
}
// Skip things like ***, #HashTagsThatMakeNoSense and 1,2345.67
if (!tmpWord.IsWord())
{
idx2 += word.Length + 1;
continue;
}
HSpellCorrections cor = Correct(tmpWord);
if (cor.SpelledCorrectly)
{
idx2 += word.Length + 1;
}
else
{
cor.Index = idx2;
return cor;
}
}
return null;
}
}
}发布于 2016-05-09 08:21:39
您可以直接使用内置的窗口拼写检查器,以便更好地控制它的行为。然后将结果应用到textbox控件中。
看看ISpellChecker。它让您添加您自己的自定义字典,并有更多的选项来控制它的行为。是的,可供UWP使用。
https://stackoverflow.com/questions/36073852
复制相似问题