Nano Hash - криптовалюты, майнинг, программирование

Как вывести консоль на несколько потоков одновременно в С#?

У меня есть программа, которая берет выходные данные консоли и записывает их в файл журнала, однако она больше не отображается в окне консоли. Есть ли способ сохранить его в окне, но также записать в файл журнала?

Обновление:

appLogStream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read);
TextWriter logtxtWriter = Console.Out;
logstrmWriter = new StreamWriter(appLogStream);
if(!console) Console.SetOut(logstrmWriter);
logstrmWriter.AutoFlush = true;
Console.WriteLine("Started at " + DateTime.Now);

console — это постоянный набор в классе. В основном он сообщает ему, использует ли он окно консоли или нет (readline не вызывается и т. д., если не в консоли).

Так есть ли способ писать как в консоль, так и в файл?

06.06.2012

  • Можете ли вы дать более подробную информацию о том, как вы отправляете вывод консоли в файл? Может небольшой пример кода? 06.06.2012
  • Кстати, если вы используете его для ведения журнала, рассмотрите возможность использования встроенной инфраструктуры ведения журнала (или других библиотек, таких как Log4net). Почитайте о TraceListener и связанных с ним классах, чтобы узнать, как можно реализовать и настроить такой вывод 1-to-many. 06.06.2012
  • Есть ли какой-то аспект среды, в которой вы работаете, который делает используемый вами подход необходимым, а не использование лучших решений, таких как класс центрального регистратора или инфраструктура трассировки .Net? 06.06.2012

Ответы:


1

Вы можете просто прочитать этот поток и распечатать его.

Это немного зависит от вашего кода, если вы назначаете выходной поток входному потоку выходного файла, это может быть немного сложнее, если вы читаете содержимое в буфер, что должно быть немного проще.


Что касается вашего обновления, я бы посоветовал вам обменять все Console на пользовательскую функцию ведения журнала, например. экземпляр MyLogger (код ниже). Который записывает ваш вывод на консоль и в ваш файл журнала.

class MyLogger {
    private FileStream appLogStream;

    public MyLogger() {
        appLogStream = new FileStream(logFile, FileMode.Append, FileAccess.Write,
                                      FileShare.Read);
        appLogStream.WriteLine("Started at " + DateTime.Now);
    }

    public Write(string msg) {
        Console.Write(msg);
        appLogStream.Write(msg);
    }

    public WriteLine(string msg) {
        Console.WriteLine(msg);
        appLogStream.WriteLine(msg);
    }
}
06.06.2012
  • Я думаю, проблема в том, что как только вы вызываете Console.SetOut, все, что вы пишете в Console, попадает в этот модуль записи, а не в стандартный вывод. Ваш код выше, скорее всего, просто дублирует вывод, отправленный в appLogStream. 06.06.2012
  • +1. По сути, это потоковый писатель 1-ко-многим. Для фактического использования может быть проще иметь список выходных писателей и клонировать вывод для всех из них. 06.06.2012
  • @rekire - я согласен, что использование класса регистратора идеально. Но его проблема может заключаться в том, что он работает с существующей большой кодовой базой, которая уже полностью разбросана с помощью Console.Write... и он пытается найти ненавязчивый способ контролировать, куда все это идет. 06.06.2012
  • К счастью, я не использовал большую базу кода, поэтому просто реализовал это. У меня есть один вопрос. Могу ли я использовать конструктор, если класс помечен как статический? Если да, то когда его уволят? 09.06.2012

  • 2

    Я думаю, вы можете сделать что-то вроде этого:

     public class ConsoleDecorator : TextWriter
    {
        private TextWriter m_OriginalConsoleStream;
    
        public ConsoleDecorator(TextWriter consoleTextWriter)
        {
            m_OriginalConsoleStream = consoleTextWriter;
        }
    
        public override void WriteLine(string value)
        {
            m_OriginalConsoleStream.WriteLine(value);
    
            // Fire event here with value
        }
    
    
        public static void SetToConsole()
        {
            Console.SetOut(new ConsoleDecorator(Console.Out));
        }
    }
    

    Вам нужно будет «зарегистрировать» оболочку, вызвав ConsoleDecorator.SetToConsole(); После этого каждый вызов Console.WriteLine будет попадать в пользовательский метод, и там вы можете запустить событие и получить текст, записанный в других местах (например, в журнале).

    если вы захотите использовать этот способ, вам нужно будет сделать класс одноэлементным, а затем вы сможете получить доступ к четной регистрации из других классов (которые должны записывать в файл журнала при срабатывании чета)

    06.06.2012

    3

    Когда вы вызываете Console.SetOut, вы указываете, куда консоль должна писать. Если вы этого не сделаете (то есть так, как обычно используется консоль), и вы вызываете Console.Write, он проверяет, есть ли у него средство записи вывода, и если нет, устанавливает его с помощью

       stream = OpenStandardOutput(256);
    

    а потом

            Encoding encoding = Encoding.GetEncoding((int) Win32Native.GetConsoleOutputCP());
            writer = TextWriter.Synchronized(new StreamWriter(stream, encoding, 256, false) { HaveWrittenPreamble = true, AutoFlush = true });
    

    Таким образом, вы должны быть в состоянии делать то, что вы делаете сейчас, и если вы также хотите вывести все на стандартный вывод, как если бы вы не перенаправляли консоль, вы можете создать свой собственный писатель, используя поток, который вы открываете сами, используя метод Console.OpenStandardOutput. Win32Native, используемый в этом коде, является внутренним, поэтому у вас нет к нему доступа, но вы можете использовать Console.OutputEncoding для получения кодировки, которую он использует.

    Вы также можете попробовать использовать свойство Console.Out для получения и сохранения стандартного вывода TextWriter непосредственно перед вызовом SetOut. Затем вы можете просто использовать это для эха на стандартный вывод.

    06.06.2012
  • Он внутренний (получен из функции GetConsoleOutputCP() в kernal32). Я хотел показать, что делает консоль. Просто попробуйте сделать простейший текстовый редактор, используя стандартный поток вывода, не дублируя буквально внутренности консоли. 06.06.2012
  • @ArlenBeiler - я отредактировал свой ответ, добавив что-то еще более простое, что вы можете попробовать. 06.06.2012
  • Хорошо, да, спасибо. Я дам всем знать завтра, как это все работает. Я думаю, что я, вероятно, объединим некоторые из этих ответов :) 06.06.2012
  • @ArlenBeiler - если Console.Out не работает, посмотрите мой отредактированный ответ о том, как получить кодировку, используемую консолью. 06.06.2012
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..