将控制台输出重定向到可读内存而不是文件?

时间:2014-07-31 15:39:10

标签: c# multithreading file memory console

我使用此代码将控制台输出重定向到文件,然后读取并显示它。我想放弃使用文件,因为我用这些控制台文件污染了我的文件夹。我怎么能在记忆中这样做?我不希望任何文件污染系统。也许我在这里尝试一些奇怪的东西。 我只想要1个线程来读取同一个应用程序的控制台输出

  • 1个申请
  • 多个线程写入控制台
  • 1个线程从控制台读取

我的工作文件代码:

private StreamWriter currentOut = null;

private void RedirectConsole()
{
    currentOut = new StreamWriter(new FileStream(filename,
        FileMode.Create, FileAccess.Write, FileShare.Read));
    currentOut.AutoFlush = true;
    Console.SetOut(currentOut);
    ThreadPool.QueueUserWorkItem(o => { Listen(); });
}

private void Listen()
{
    StreamReader fileIn = new StreamReader(new FileStream(filename,
        FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
    while (true)
    {
        try
        {
            if (!fileIn.EndOfStream)
            {
                string a = fileIn.ReadLine();
                MessageBox.Show(a);
            }
            Thread.Sleep(25);
        }
        catch { }
    }
}

This似乎就是我想要的。但我无法实现(帮助?)。文件就像一个缓冲区。你从一端写到它并从另一端读。我需要内存相同。

3 个答案:

答案 0 :(得分:1)

尝试:

private StreamWriter currentOut = null;
private MemoryStream ms = new MemoryStream();

private void RedirectConsole()
{
    currentOut = new StreamWriter(ms);
    currentOut.AutoFlush = true;
    Console.SetOut(currentOut);
    ThreadPool.QueueUserWorkItem(o => { Listen(); });
}

private void Listen()
{
    StreamReader fileIn = new StreamReader(ms);
    // ...
}

答案 1 :(得分:0)

我最终编写了一个派生流类,并用我自己的流替换了FileStream。我应该避免这样做。但由于我找不到工作解决方案,这也是一个很好的做法。像这样:

public class MyStream: Stream
{
    private byte[] internalBuffer = new byte[4096];

    // ...

    public override int Read(byte[] buffer, int offset, int count)
    {
        // used by StreamReader
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        // used by StreamWriter
    }
}

override所有其他内容,在扩展internalBuffer和处理传递的数据时处理多线程。

答案 2 :(得分:0)

使用MemoryStream的问题在于读取位置随写入位置前进。管道(System.IO.Pipes命名空间)是用作临时缓冲区的更好选择,其中读取位置需要独立于写入位置而前进。不可否认,这或多或少与您的工作解决方案完全相同,但它不需要自己实现缓冲区。

class ConsoleRedirector : IDisposable
{
    private TextWriter originalOut = Console.Out;
    private AnonymousPipeServerStream consoleOutServerPipe;
    private StreamWriter currentOut;

    public ConsoleRedirector()
    {
        this.consoleOutServerPipe = new AnonymousPipeServerStream(PipeDirection.Out);
        this.currentOut = new StreamWriter(this.consoleOutServerPipe);
        this.currentOut.AutoFlush = true;
        Console.SetOut(this.currentOut);
        ThreadPool.QueueUserWorkItem(o => { this.Listen(); });
    }

    private void Listen()
    {
        AnonymousPipeClientStream consoleOutClientPipe = new AnonymousPipeClientStream(PipeDirection.In, this.consoleOutServerPipe.ClientSafePipeHandle);
        using (StreamReader fileIn = new StreamReader(consoleOutClientPipe))
        {
            // ...
        }
    }

    public void Dispose()
    {
        this.currentOut.Dispose();
        Console.SetOut(this.originalOut);
    }
}