0

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

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 用于中间结果时我的结果会有所不同,是否有更清洁、更灵活的方法?(如果可以选择是否要保存中间结果,我想努力解决)。

4

2 回答 2

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();
}
于 2011-05-06T08:27:16.160 回答
0

我有一个更改您的代码的建议。也许您可以使用 IEnumerable 而不是使用 Streams 和 TextReaders。

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

上一个操作的结果作为参数提供给下一个。因此,它按照以下 Operation3(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");
        }
    }
}
于 2011-05-06T11:36:10.857 回答