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

コードを変更する提案があります。Streams と TextReaders を使用する代わりに、IEnumerable を使用することもできます。

以下のサンプルを参照してください (これは単なるサンプルです。サンプルを簡単にするためにエラー処理は含まれていません)。

前の操作の結果は、次の操作へのパラメーターとして提供されます。したがって、次の Operation3(Operation2(Operation1))) として実行されます。

以下の最初のサンプルは、ファイルに含まれる行を 1 行ずつ読み取り、変更しています。次の 2 番目のサンプルは、ファイル全体を読み取り、すべての行を次の操作に提供する行を変更しています (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 に答える