Хобрук: Ваш путь к мастерству в программировании

Поток чтения С#

Я хочу прочитать файл .txt на C#, но не буду читать все строки одновременно. Например, рассмотрим 500 строк текстового файла. Я хочу, чтобы функция выполнялась 25 раз и каждый раз читала 20 последовательных строк. При первом вызове функции будут прочитаны строки с 1 по 20, а при втором вызове будут прочитаны строки с 21 по 40.

Ниже простой код делает это на С++, но я не знаю, как это сделать на С#:

string readLines(ifstream& i)
{
     string totalLine="", line = "";
     for(int i = 0; i < 20; i++){
          getline(i, line);

          totalLine += line;
     }
     return totalLine;
}

int main()
{

     // ...
     ifstream in;
     in.open(filename.c_str());
     while(true){
         string next20 = readLines(in);
         // so something with 20 lines.
     }
     // ...

}
14.08.2013

  • Как читать текст из файла: 14.08.2013
  • Код, который вы дали на C++, вообще этого не делает - он просто зацикливается, читая все строки. Это легко сделать и на C#... foreach (string line in File.ReadLines(...)). Пакетная обработка не так уж плоха в С#... 14.08.2013
  • Это просто быстрый пример. Я имел в виду, что если вы поместите оператор while в функцию, и даже если вы преждевременно прекратите чтение файла, она продолжится с того места, где остановилась. 14.08.2013
  • @MertToka: Этот быстрый пример не демонстрирует, что вы пытаетесь сделать, - он, по сути, ничего не добавляет к вопросу. 14.08.2013
  • @JonSkeet, пожалуйста, посмотрите правку. 14.08.2013
  • Это определенно лучше, хотя first20 вводит в заблуждение, учитывая, что на самом деле это будут только первые 20 строк на первой итерации. next20 было бы лучше. 14.08.2013

Ответы:


1

Здесь есть различные варианты, но один простой подход:

using (var reader = File.OpenText("file.txt"))
{
    for (int i = 0; i < 25; i++)
    {
        HandleLines(reader);
    }
}

...

private void HandleLines(TextReader reader)
{
    for (int i = 0; i < 20; i++)
    {
        string line = reader.ReadLine();
        if (line != null) // Handle the file ending early
        {
            // Process the line
        }
    }
}
14.08.2013

2

Если вы пытаетесь вызвать LineRead() наименьшее возможное количество раз и хотите минимально использовать память, вы можете сначала проиндексировать строки в вашем файле:

  1. Проанализируйте файл один раз и индексируйте позицию каждой строки в FileStream.
  2. Вызывайте ReadLine() только в нужном месте.

eg:

// Parse the file
var indexes = new List<long>();
using (var fs = File.OpenRead("text.txt"))
{
    indexes.Add(fs.Position);
    int chr;
    while ((chr = fs.ReadByte()) != -1)
    {
        if (chr == '\n')
        {                        
            indexes.Add(fs.Position);
        }
    }
}

int minLine = 21;
int maxLine = 40;

// Read the line
using (var fs = File.OpenRead("text.txt"))
{
    for(int i = minLine ; i <= maxLine ; i++)
    {
        fs.Position = indexes[ i ];
        using (var sr = new StreamReader(fs))
            Console.WriteLine(sr.ReadLine());

}

Ваше здоровье !

14.08.2013

3

Вы можете написать метод Batch() следующим образом:

public static IEnumerable<string> Batch(IEnumerable<string> input, int batchSize)
{
    int n = 0;
    var block = new StringBuilder();

    foreach (var line in input)
    {
        block.AppendLine(line);

        if (++n != batchSize)
            continue;

        yield return block.ToString();
        block.Clear();
        n = 0;
    }

    if (n != 0)
        yield return block.ToString();
}

И назовите это так:

string filename = "<Your filename goes here>";
var batches = Batch(File.ReadLines(filename), 20);

foreach (var block in batches)
{
    Console.Write(block);
    Console.WriteLine("------------------------");
}
14.08.2013

4

Упс. GroupBy не оценивает лениво, поэтому он будет жадно потреблять весь файл

<удар>

var twentyLineGroups = 
    File.ReadLines(somePath)
        .Select((line, index) => new {line, index})
        .GroupBy(x => x.index / 20)
        .Select(g => g.Select(x => x.line));

foreach(IEnumerable<string> twentyLineGroup in twentyLineGroups)
{
    foreach(string line in twentyLineGroup)
    {
        //tada!
    }
}

14.08.2013
  • Итак, этот фрагмент кода на самом деле делит строки на 20, а затем перебирает строки, перебирая группы, верно? Я очень не знаком с функциями первого оператора. 14.08.2013
  • Новые материалы

    Dall-E 2: недавние исследования показывают недостатки в искусстве, созданном искусственным интеллектом
    DALL-E 2 — это всеобщее внимание в индустрии искусственного интеллекта. Люди в списке ожидания пытаются заполучить продукт. Что это означает для развития креативной индустрии? О применении ИИ в..

    «Очень простой» эволюционный подход к обучению с подкреплением
    В прошлом семестре я посетил лекцию по обучению с подкреплением (RL) в моем университете. Честно говоря, я присоединился к нему официально, но я редко ходил на лекции, потому что в целом я нахожу..

    Освоение информационного поиска: создание интеллектуальных поисковых систем (глава 1)
    Глава 1. Поиск по ключевым словам: основы информационного поиска Справочная глава: «Оценка моделей поиска информации: подробное руководство по показателям производительности » Глава 1: «Поиск..

    Фишинг — Упаковано и зашифровано
    Будучи старшим ИТ-специалистом в небольшой фирме, я могу делать много разных вещей. Одна из этих вещей: специалист по кибербезопасности. Мне нравится это делать, потому что в настоящее время я..

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..