使用一个内存流进行多个文件搜索迭代

时间:2011-05-06 08:22:01

标签: c# memorystream ref textwriter

我有几个方法,每个方法都对文本文件应用一个操作,其中下一个操作需要将前一个操作的结果作为输入:

private TextReader input = new StreamReader("input.txt");
private TextWriter output = new StreamWriter("output.txt");
MemoryStream result_1 = new MemoryStream();
MemoryStream result_2 = new MemoryStream();

Operation_1(input, ref result_1);
Operation_2(result_1, ref result_2);
Operation_3(result_2, output);

Operation_1:

的代码
   private void Operation_1(TextReader input, ref MemoryStream output)
    {
        TextWriter outputWriter = new StreamWriter(output);
        String line;

        while (input.Peek() >= 0) //while not end of file
        {
            line = input.ReadLine();
            //perform operation on line
            outputWriter.writeline(line);
        }
        input.Close();
    }

operation_2:

的代码
   private void Operation_2(TextReader input, ref MemoryStream output)
    {
        input.Seek(0, SeekOrigin.Begin); //reset stream to start of file
        TextReader inputReader = new StreamReader(input);
        TextWriter outputWriter = new StreamWriter(output);
        String line;

        while (inputReader.Peek() >= 0) //while not end of file
        {
            line = inputReader.ReadLine();
            //perform operation on line
            outputWriter.writeline(line);
        }
        inputReader.Close();
    }

operation_3的代码:

    private void operation_3(MemoryStream input, TextWriter output)
    {
       input.Seek(0, SeekOrigin.Begin);  //reset stream to start of file
       TextReader inputReader = new StreamReader(input);
       String line;

       while (inputReader.Peek() >= 0) //while not end of file
       {
            line = inputReader.ReadLine();
            //perform operation on line
            output.writeline(line);
       }
       inputReader.Close();
       output.Close();
    }

现在的问题是,我没有得到与将每个中间结果存储到硬盘上的物理txt文件并将该文件用于下一个操作相同的结果。缺少几行和文件末尾。

此外,这似乎不是一种非常干净和通用的方式。

因此,我的问题;为什么我的结果在使用MemoryStream作为中间结果时有所不同,是否有更简洁,更灵活的方法呢? (如果你想保存中间结果,我想选择一个解决方案。)

2 个答案:

答案 0 :(得分:1)

  • 他们是不同的,因为你忘记了冲你的作家。
  • 不需要ref修饰符,因为您未在操作中创建新的MemoryStream

你的方法会更加清洁:

private void Operation_1(TextReader input, Stream output)
{
    TextWriter outputWriter = new StreamWriter(output);
    String line;

    outputWriter.Write(input.ReadToEnd());
    outputWriter.Flush();

    input.Close();
}

private void Operation_2(Stream input, Stream output)
{
    input.Seek(0, SeekOrigin.Begin); //reset stream to start of file
    TextReader inputReader = new StreamReader(input);
    TextWriter outputWriter = new StreamWriter(output);

    outputWriter.Write(inputReader.ReadToEnd());
    outputWriter.Flush();
    inputReader.Close();
}

operation_3的代码:

private void operation_3(Stream input, TextWriter output)
{
   input.Seek(0, SeekOrigin.Begin);  //reset stream to start of file
   TextReader inputReader = new StreamReader(input);

   output.Write(inputReader.ReadToEnd());

   inputReader.Close();
   output.Flush();
   output.Close();
}

答案 1 :(得分:0)

我建议您更改代码。也许不使用Streams和TextReaders,你可以使用IEnumerable。

请参阅下面的示例(这只是一个示例。不包括错误处理以保持示例简单。)

前一个操作的结果作为参数提供给下一个。因此,它执行如下操作3(Operation2(Operation1)))。

下面的第一个示例是逐行读取和更改文件中包含的行 下面的第二个示例是读取整个文件并更改提供所有行的行到下一个操作(lines.ToArray()读取整个文件)。

使用流时,您必须要小心它们在所需的时间正确处理(例如StreamReader在StreamReader处理时默认关闭内部流)。

using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main()
        {
            //line per line...
            File.WriteAllLines
                (
                    @"C:\temp\output.txt",
                    ChangeLines(File.ReadLines(@"C:\temp\input.txt"),
                                line =>
                                LineOperation3
                                    (
                                        LineOperation2
                                            (
                                                LineOperation1(line)
                                            )
                                    )
                        )
                );

            //lines per lines...
            File.WriteAllLines
               (
                   @"C:\temp\output2WithCount.txt",
                   ChangeLines(File.ReadLines(@"C:\temp\input.txt"),
                               lines =>
                                        LinesCountOperation
                                        (
                                            LinesCountOperation
                                            (
                                                LinesCountOperation(lines,LineOperation1),
                                                LineOperation2
                                            )
                                            , LineOperation3
                                          )
                       )
               );
        }

        private static IEnumerable<string> ChangeLines(IEnumerable<string> lines, Func<string, string> lineFunc)
        {
            foreach (var line in lines)
            {
                yield return lineFunc(line);
            }
        }

        private static IEnumerable<string> ChangeLines(IEnumerable<string> lines, Func<IEnumerable<string>, IEnumerable<string>> linesFunc)
        {
            foreach(var changedLine in linesFunc(lines))
            {
                if (changedLine != null)
                {
                    yield return changedLine;
                }
            }
        }

        private static IEnumerable<string> LinesCountOperation(IEnumerable<string> lines, Func<string, string> lineFunc)
        {
            var readAllLines = lines.ToArray();
            var linesCount = readAllLines.Count();

            foreach (var line in readAllLines)
            {
                var changedLine = lineFunc(line);
                if (changedLine == null)
                {
                    continue;
                }
                yield return string.Format(CultureInfo.InvariantCulture, "{0}-{1}", linesCount, changedLine);
            }
        }

        private static string LineOperation1(string line)
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}{1}", line, "1");
        }

        private static string LineOperation2(string line)
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}{1}", line, "2");
        }

        private static string LineOperation3(string line)
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}{1}", line, "3");
        }
    }
}