使用Using和Yield Return从文件中读取文本行

3

我有以下方法,使用Yield Return从文件中读取大量( >1m )文本行。

    private static IEnumerable<string> ReadLineFromFile(TextReader fileReader)
    {
        using (fileReader)
        {
            string currentLine;
            while ((currentLine = fileReader.ReadLine()) != null)
            {
                yield return currentLine;
            }
        }
    }

我需要能够将此方法返回的每10行写入不同的文件。

我如何使用此方法而无需枚举所有行?

非常感谢任何答案。


@Kevin 哪里出了问题?! :-) - MaYaN
这段代码...我手头没有编译器,但看起来每次迭代10行应该没问题吧? - Rym
代码可以运行,我的问题是调用者如何使用这个方法?当我将IEnumerable材料化为List时,调用者如何收集前10行,因为整个文件都会被读取到末尾。我需要访问批处理中的行,比如说每次10行。希望这有意义。 - MaYaN
请参考这里接受的答案,了解如何对 IEnumerable 进行分块:http://stackoverflow.com/questions/12186376/chunk-ienumerable-icollection-class-c-sharp-2-0 - Mike Zboray
这个链接中的答案非常好,它意味着你只需要使用foreach(var batch in Chunk(ReadLineFromFile(filename), BATCH_SIZE) { // 处理 List<T> }就可以了。 - Rym
@mikez - 实际上我再次看了一下那个方法,确实是一个非常优雅的解决方案。再次感谢。 - MaYaN
3个回答

2

我想我终于让它工作了 :-)

        var listOfBufferedLines = ReadLineFromFile(ReadFilePath);

        var listOfLinesInBatch = new List<string>();
        foreach (var line in listOfBufferedLines)
        {
            listOfLinesInBatch.Add(line);

            if (listOfLinesInBatch.Count % 1000 == 0)
            {
                Console.WriteLine("Writing Batch.");
                WriteLinesToFile(listOfLinesInBatch, LoadFilePath);
                listOfLinesInBatch.Clear();
            }
        }

        // writing the remaining lines
        WriteLinesToFile(listOfLinesInBatch, LoadFilePath);

0
如果您运行以下代码,您会发现您所需要做的就是在foreach循环内调用您的方法,它将逐一迭代,您只需要将其缓冲到您选择的批处理大小的某个地方即可。
static void Main (string [] args)
{
    int batch_size = 5;
    string buffer = "";
    foreach (var c in EnumerateString("THISISALONGSTRING")) 
    {               
        // Check if it's time to split the batch
        if (buffer.Length >= batch_size) 
        {
            // Process the batch
            buffer = ProcessBuffer(buffer);
        }

        // Add to the buffer
        buffer += c;
    }

    // Process the remaining items
    ProcessBuffer(buffer);

    Console.ReadLine();
}

public static string ProcessBuffer(string buffer)
{
    Console.WriteLine(buffer);  
    return "";
}

public static IEnumerable<char> EnumerateString(string huh)
{
    for (int i = 0; i < huh.Length; i++) {
        Console.WriteLine("yielded: " + huh[i]);
        yield return huh[i];
    }
}

2
像这样在循环中连接字符串通常不是一个好主意。 - svick
我感觉在答案中强调何时使用 StringBuilder 已经超出了范围 :) - Rym
2
我认为所有的答案都应该使用最佳实践。你不必强调它,但你应该在你的回答中使用它。 - svick

0

这绝对不是一个优雅的解决方案,但它可以工作。

static void Main(string[] args)
        {

            try
            {
                System.IO.TextReader readFile = new StreamReader(@"C:\Temp\test.txt");
                int count = 0;
                List<string> lines= new List<string>();
                foreach (string line in ReadLineFromFile(readFile))
                {
                    if (count == 10)
                    {
                        count = 0;
                        ProcessChunk(lines);
                        lines.Add(line);
                    }
                    else
                    {
                        lines.Add(line);
                        count++;
                    }

                }
                //PROCESS the LINES
                ProcessChunk(lines);

                Console.ReadKey();
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private static void ProcessChunk(List<string> lines)
        {
            Console.WriteLine("----------------");
            lines.ForEach(l => Console.WriteLine(l));
            lines.clear();
        }

        private static IEnumerable<string> ReadLineFromFile(TextReader fileReader)
        {
            using (fileReader)
            {
                string currentLine;
                while ((currentLine = fileReader.ReadLine()) != null)
                {
                    yield return currentLine;
                }
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接