Текст из файла в строку

379
08 февраля 2017, 22:30

Программа должна считывать из текстового файла (.txt) весь текст и записывать его в массив строк по 100 символов. Файлы большого объема (от 10 Мбайт). Использую File.ReadAllText для загона всего текста в одну строку, а потом ее бью на части и загоняю в массив строк. Интерфейс программы сразу же "не отвечает". Можно это сделать как-то быстрее и проще? Или тогда лучше использовать async/await?

Answer 1

Вот, отличное решение, через метод-расширение:

public static class StringExtensions
{
    public static IEnumerable<string> SplitChunk(this string s, int chunkSize)
    {
        int chunkCount = s.Length / chunkSize;
        for (int i = 0; i < chunkCount; i++)
            yield return s.Substring(i * chunkSize, chunkSize);
        if (chunkSize * chunkCount < s.Length)
            yield return s.Substring(chunkSize * chunkCount);
    }
}

private async Task<IEnumerable<string>> GetAllStrings(int chunkSize, string filePath)
{
    using (var sr = File.OpenText(filePath))
    {
        var rawText = await sr.ReadToEndAsync();
        var text = rawText.Replace(Environment.NewLine, "");
        return text.SplitChunk(chunkSize).ToList();
    }
}

Использование:

var listChunk = await GetAllStrings(100,"c:\\temp\\2.txt");
Answer 2

Ещё одно улучшение вдвое по скорости, за счёт увеличения буфера до 4К:

List<string> SplitByChars(int chunkSize, string path)
{
    List<string> result = new List<string>();
    using (var f = File.OpenText(path))
    {
        var buffer = new char[4096];
        StringBuilder currentLine = new StringBuilder(chunkSize);
        int readCount;
        do
        {
            readCount = f.ReadBlock(buffer, 0, buffer.Length);
            for (int i = 0; i < readCount; i++)
            {
                char c = buffer[i];
                if (c == '\r' || c == '\n')
                    continue;
                currentLine.Append(c);
                if (currentLine.Length == chunkSize)
                {
                    result.Add(currentLine.ToString());
                    currentLine.Clear();
                }
            }
        } while (readCount > 0);
        if (currentLine.Length > 0)
            result.Add(currentLine.ToString());
    }
    return result;
}

Старый вариант:

IEnumerable<string> SplitByChars(int chunkSize, string path)
{
    List<string> result = new List<string>();
    using (var f = File.OpenText(path))
    {
        var buffer = new char[chunkSize];
        StringBuilder currentLine = new StringBuilder(chunkSize);
        int readCount;
        do
        {
            var oldLength = currentLine.Length;
            var rest = chunkSize - currentLine.Length;
            readCount = f.ReadBlock(buffer, 0, rest);
            currentLine.Append(buffer, 0, rest);
            currentLine.Replace("\r", "", oldLength, rest);
            currentLine.Replace("\n", "", oldLength, currentLine.Length - oldLength);
            if ((readCount == 0 && currentLine.Length > 0) ||
                currentLine.Length == chunkSize)
            {
                result.Add(currentLine.ToString());
                currentLine.Clear();
            }
        } while (readCount > 0);
    }
    return result;
}

Я старался не грузить память чтением длинных строк, максимальное потребление памяти — один буфер размером в chunkSize и один StringBuilder с capacity в chunkSize.

Пользоваться так:

var result = await Task.Run(() => SplitByChars(100, path));

Предыдущий вариант с ReadBlockAsync был примерно втрое медленнее.

Здесь слишком много работы «вручную», возможно, есть более изящное решение.

READ ALSO
Цифровая подпись интеркассы в asp.net [требует правки]

Цифровая подпись интеркассы в asp.net [требует правки]

Как сформировать цифровую подпись интеркассы в aspnet mvc

340
Поиск элеметов XML и их вывод

Поиск элеметов XML и их вывод

Есть XML, который имеет простую структуру:

362
Расшифровка пиктограмм в Visual Studio 2015

Расшифровка пиктограмм в Visual Studio 2015

Не могу найти никакой документации по вопросу, о том, что означают различные значки и пиктограммы в VS2015Пользуясь отладчиком столкнулся с непонятными...

435