9

私のプログラムでは、基本的にファイルを読み込んで処理を行い、それをメモリストリームとしてメインプログラムに戻します。このメモリストリームはストリームリーダーによって処理されます。これはすべて私のメインの横にあるクラスによって処理されます。

問題は、別のクラスのメソッドからメモリストリームを返すときに、「canread」変数がfalseに設定されているため、streamreaderの初期化が失敗することです。

以下は、発生している問題の例です(ただし、ここでは他のクラスのメモリストリームに書き込んでいますが、それを返すと同じエラーが発生します。

「Otherclass」という名前のクラス:

public static MemoryStream ImportantStreamManipulator()
{
   MemoryStream MemStream = new MemoryStream();

   StreamWriter writer = new StreamWriter(MemStream);
   using (writer)
   {
       //Code that writes stuff to the memorystream via streamwriter

       return MemStream;
   }
}

メインプログラムでの関数呼び出し:

MemoryStream MStream = Otherclass.ImportantStreamManipulator();
StreamReader reader = new StreamReader(MStream);

「returnMemStream」にブレークポイントを設定しても、「CanRead」プロパティは引き続きtrueに設定されています。メイン関数に戻り、戻り値をMStreamに書き込むようにステップすると、「CanRead」プロパティがfalseに設定されます。これにより、StreamReaderで、MStreamを読み取ることができなかったという例外が発生します(プロパティが示すように)。データは本来あるべきストリームバッファにありますが、私はそれを取り出すことができません。

メインに戻されたときに「CanRead」がtrueを報告するように設定するにはどうすればよいですか?または、MemoryStreamがどのように機能し、やりたいことをどのように達成するかを誤解していますか?

4

3 に答える 3

29

これが問題です:

using (writer)
{
    //Code that writes stuff to the memorystream via streamwriter

    return MemStream;
}

ライターを閉じています。これにより、が閉じますMemoryStream。この場合、あなたはそれをしたくありません...あなたはライターをフラッシュし、そして巻き戻す必要がありますがMemoryStream。コードを次のように変更するだけです。

public static MemoryStream ImportantStreamManipulator()
{
   // Probably add a comment here stating that the lack of using statements
   // is deliberate.
   MemoryStream stream = new MemoryStream();

   StreamWriter writer = new StreamWriter(stream);
   // Code that writes stuff to the memorystream via streamwriter

   writer.Flush();
   stream.Position = 0;
   return stream;
}
于 2012-07-17T18:38:41.027 に答える
2

StreamWriterメモリストリームの所有権を取得し、usingステートメントが終了すると、MemoryStreamも閉じられます。

BaseStreamを閉じずにStreamWriterを閉じる方法はありますか?を参照してください。。

于 2012-07-17T18:38:38.163 に答える
0

他の人が述べているように、問題は、StreamWriterが閉じられたときにストリームが閉じられることです。これに対処する1つの可能な方法は、MemoryStreamではなくバイト配列を返すことです。これにより、ガベージコレクタによって破棄する必要のある実行時間の長いオブジェクトが回避されます。

public static void Main()
{
    OutputData(GetData());
}

public static byte[] GetData()
{
    byte[] binaryData = null;

    using (MemoryStream ms = new MemoryStream())
    using (StreamWriter sw = new StreamWriter(ms))
    {
        string data = "My test data is really great!";

        sw.Write(data);
        sw.Flush();

        binaryData = ms.ToArray();
    }

    return binaryData;
}

public static void OutputData(byte[] binaryData)
{
    using (MemoryStream ms = new MemoryStream(binaryData))
    using (StreamReader sr = new StreamReader(ms))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}

別の方法は、戻る前にストリームを別のストリームにコピーすることです。ただし、これには、StreamReaderを使用して後でアクセスするとそのストリームが閉じられるという問題があります。

public static void RunSnippet()
{
    OutputData(GetData());
}

public static MemoryStream GetData()
{
    MemoryStream outputStream = new MemoryStream();

    using (MemoryStream ms = new MemoryStream())
    using (StreamWriter sw = new StreamWriter(ms))
    {
        string data = "My test data is really great!";

        sw.Write(data);
        sw.Flush();

        ms.WriteTo(outputStream);
        outputStream.Seek(0, SeekOrigin.Begin);
    }

    return outputStream;
}

public static void OutputData(MemoryStream inputStream)
{
    using (StreamReader sr = new StreamReader(inputStream))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}   
于 2012-07-17T19:12:16.503 に答える