首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UWP应用程序中的拼写库(如hun拼写)?

UWP应用程序中的拼写库(如hun拼写)?
EN

Stack Overflow用户
提问于 2016-03-18 00:05:00
回答 3查看 1.1K关注 0票数 5

我正在为作者移植一个应用程序到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应用程序中运行得很好。我也必须替换这个功能--希望与拼写检查引擎相同。然而,如果你知道一个好的辞典引擎(但它不拼写检查),这也是好的!

谢谢你!!

EN

回答 3

Stack Overflow用户

发布于 2016-03-20 16:22:32

我下载了NHunspell库的源代码,并试图构建一个支持UWP的库,但是我发现了编组NHunspell的问题。

这个包装载了只在x86和x64架构下工作的dll,因此在arm (移动电话、平板电脑)中,应用程序将无法工作。

该包用系统调用加载dll:

代码语言:javascript
复制
    [DllImport("kernel32.dll")]
    internal static extern IntPtr LoadLibrary(string fileName);

我认为在UWP中工作需要重写,因为UWP使用的是沙箱。

国际水文学组织只有两个选择:

1)在UWP的限制下重写编组类。

2)不要在你的程序中使用饥饿咒语。

我对UWP的dll不太了解,但我相信重写可能会非常困难。

票数 3
EN

Stack Overflow用户

发布于 2016-03-25 14:17:23

正如我所承诺的,这是我为做拼写检查而建的课程。

代码语言:javascript
复制
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;
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2016-05-09 08:21:39

您可以直接使用内置的窗口拼写检查器,以便更好地控制它的行为。然后将结果应用到textbox控件中。

看看ISpellChecker。它让您添加您自己的自定义字典,并有更多的选项来控制它的行为。是的,可供UWP使用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36073852

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档