Я собираюсь сделать сингальский словарь английского языка. Итак, у меня есть файл, который содержит сингальский смысл для каждого английского слова. Поэтому я подумал загрузить его, пока загружается форма. Поэтому я добавил следующую команду, чтобы получить все содержимое файла в строковую переменную. SO я использовал следующую команду в методе FormLoad,
private string DictionaryWords = "";
private string ss = null;
...
private void Form1_Load(object sender, EventArgs e)
{
this.BackColor = ColorTranslator.FromHtml("#AFC3E0");
string fileName = @"SI-utf8.Txt";
using (StreamReader sr = File.OpenText(fileName))
{
while ((ss = sr.ReadLine()) != null)
{
DictionaryWords += ss;
}
}
}
Но, к сожалению, в этом текстовом файле более 130000 строк, а его размер превышает 5 МБ. ТАК моя winform не загружается.
Увидеть изображение
Мне нужно загрузить это быстрее, чтобы winform использовал форму REGEX, получая правильное значение для каждого английского слова. Может ли кто-нибудь сказать мне, как это сделать. Я пробовал все.
Загрузите этот огромный файл в мой проект менее чем за 15 минут, и вам нужно будет использовать Regex для поиска каждого английского слова.
Что такое DictionaryWords, пожалуйста? DictionaryWords += ss; выглядит очень подозрительно.
Еще одна возможность - запустить асинхронную задачу Form1_Load, тогда, когда вы захотите получить словарь, вы можете await выполнить ранее запущенную задачу.
Каково ожидаемое регулярное выражение? Обратите внимание, что объединение всех слов в одно регулярное выражение — плохая идея.
Судя по всему, DictionaryWords — это строка? Если это так, я настоятельно рекомендую изменить его на настоящий словарь. Строки неизменяемы в С#, это означает, что каждый раз, когда вы что-то добавляете к строке, будет создаваться новая строка. По сути, вы читаете 130 тыс. строк, а затем для каждой строки дублируете текущую строку. Чем больше, тем медленнее. TL;DR: перейти на словарь или список<string>
DictionaryWords
. Я подозреваю, что проблема здесь не в загрузке текстового файла, который не такой уж большой, а в обработке содержимого, которая здесь является проблемой.
Словарь @DmitryBychenko означает строковую переменную, в которой хранится содержимое txt файла.
@Ryan Gabriel: Итак, мы знаем виновника (DictionaryWords += ss), давайте избавимся от него: пожалуйста, посмотрите мое редактирование. Пожалуйста, не то чтобы преступник мог иметь помощника, который может быть регулярным выражением
Ну слишком мало кода для анализа. я подозреваю, что
DictionaryWords += ss;
Является уголовником: добавление строки 130000 раз, что означает повторное создание довольно длинной строки снова и снова, вполне может поставить систему на колени, но у меня нет строгого доказательства (я спрашивал о DictionaryWords в комментарии). Еще один возможный кандидат на вину — неизвестное мне ваше регулярное выражение.
Поэтому позвольте мне попытаться решить проблему с нуля.
SI-utf8.Txt
.У меня есть что-то вроде этого:
using System.IO;
using System.Linq;
using System.Threading.Tasks;
...
// Loading dictionary (async, since dictionary can be quite long)
// static: we want just one dictionary for all the instances
private static readonly Task<IReadOnlyDictionary<string, string>> s_Dictionary =
Task<IReadOnlyDictionary<string, string>>.Run(() => {
char[] delimiters = { ' ', '\t' };
IReadOnlyDictionary<string, string> result = File
.ReadLines(@"SI-utf8.Txt")
.Where(line => !string.IsNullOrWhiteSpace(line))
.Select(line => line.Split(delimiters, StringSplitOptions.RemoveEmptyEntries))
.Where(items => items.Length == 2)
.ToDictionary(items => items[0],
items => items[1],
StringComparer.OrdinalIgnoreCase);
return result;
});
Затем нам нужна часть перевода:
// Let it be the simplest regex: English letters and apostrophes;
// you can improve it if you like
private static readonly Regex s_EnglishWords = new Regex("[A-Za-z']+");
// Tanslation is async, since we have to wait for dictionary to be loaded
private static async Task<string> Translate(string englishText) {
if (string.IsNullOrWhiteSpace(englishText))
return englishText;
var dictionary = await s_Dictionary;
return s_EnglishWords.Replace(englishText,
match => dictionary.TryGetValue(match.Value, out var translation)
? translation // if we know the translation
: match.Value); // if we don't know the translation
}
Использование:
// Note, that button event should be async as well
private async void button1_Click(object sender, EventArgs e) {
TranslationTextBox.Text = await Translate(OriginalTextBox.Text);
}
Редактировать: Итак, DictionaryWords является string и, следовательно,
DictionaryWords += ss;
Является уголовником. Пожалуйста, не добавляйте string в (глубокий) цикл: каждое добавление заново создает медленную строку. Если вы настаиваете на зацикливании, используйте StringBuilder:
// Let's pre-allocate a buffer for 6 million chars
StringBuilder sb = new StringBuilder(6 * 1024 * 1024);
using (StreamReader sr = File.OpenText(fileName))
{
while ((ss = sr.ReadLine()) != null)
{
sb.Append(ss);
}
}
DictionaryWords = sb.ToString();
Или зачем вообще зацикливаться? Позвольте .net сделать всю работу за вас:
DictionaryWords = File.ReadAllText(@"SI-utf8.Txt");
Редактировать 2: если фактический размер файла не так уж велик (только DictionaryWords += ss; портит удовольствие), вы можете придерживаться простого синхронного решения:
private static readonly Regex s_EnglishWords = new Regex("[A-Za-z']+");
private static readonly IReadOnlyDictionary<string, string> s_Dictionary = File
.ReadLines(@"SI-utf8.Txt")
.Where(line => !string.IsNullOrWhiteSpace(line))
.Select(line => line.Split(new char[] { ' ', '\t' },
StringSplitOptions.RemoveEmptyEntries))
.Where(items => items.Length == 2)
.ToDictionary(items => items[0],
items => items[1],
StringComparer.OrdinalIgnoreCase);
private static string Translate(string englishText) {
if (string.IsNullOrWhiteSpace(englishText))
return englishText;
return s_EnglishWords.Replace(englishText,
match => s_Dictionary.TryGetValue(match.Value, out var translation)
? translation
: match.Value);
}
Тогда использование довольно просто:
// Note, that button event should be async as well
private void button1_Click(object sender, EventArgs e) {
TranslationTextBox.Text = Translate(OriginalTextBox.Text);
}
Вот это самое правильное решение. Для простоты вы можете предоставить неасинхронную версию этого, предполагая, что фактическое чтение текстового файла происходит достаточно быстро, чтобы пользователь действительно не заметил.
Вау... Мистер Дмитрий Быченко.. Сэр, вы сэкономили мне время, Большое спасибо. ваш метод работает.
Что значит "не загружается"?