none
Application Console - Vérifier la présence de données dans l'entrée standard RRS feed

  • Question

  • Bonjour à tou(te)s,

    Je suis en train d'écrire une application console qui doit se comporter comme une commande DOS, et en particulier, lire des données sur l'entrée standard si des données lui ont été "pipées".

    Or, quand je tente de lire l'entrée standard, avec Console.In.ReadToEnd(), et que l'entrée standard est vide, la console s'affiche et attend que je tape des données au clavier au lieu de me renvoyer "null" ou autre chose.

    J'ai fait plusieurs essais :

        - Utiliser la méthode Peek() au lieu de ReadToEnd() : Même comportement si l'entrée standard est vide, la console s'affiche et attend que je tape

        - Utiliser une boucle avec des Console.In.ReadLine(), tant qu'il ne renvoie pas null... Mais même résultat...

        - Caster le Console.In en TextStream, ou en MemoryStream pour avoir le Length... Aucun de ces casts ne fonctionnent à cause du type réel SyncTextReader du Console.In...

        - Utiliser la méthode statique Console.OpenStandardInput() :

    StreamReader f = new StreamReader(Console.OpenStandardInput());
    if (f.BaseStream.Length == 0)
        throw new ArgumentException("Arguments incorrects.");

    Mais lorsque j'accède au BaseStream, la propriété Length n'est pas supportée...

    Comment peut-on faire alors pour détecter si l'entrée standard contient des données sans que la console ne reprenne la main pour attendre une saisie ?

    Merci d'avance !

    EuG

     

    mercredi 25 avril 2012 15:38

Réponses

  • Je l'écrirait plutôt comme ça:

    using System;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace ConsoleApplicationTest
    {
        class Program
        {
            const int bufferSize = 1024;
    
            static void Main(string[] args)
            {
                Console.WriteLine("\nTapez et retapez n'importe quoi puis appuyez sur la touche Entrée:");
                new Thread(new ThreadStart(checkStandrardInputOnce)).Start(); // Lancer la première capture
                Thread.Sleep(1000); // attendre un peu
                new Thread(new ThreadStart(checkStandrardInputForever)).Start(); // Lancer la deuxième capture
            }
    
            static void checkStandrardInputOnce()
            {
                var buffer = new byte[bufferSize];
                var stream = Console.OpenStandardInput();
    
                stream.BeginRead(buffer, 0, buffer.Length, a =>
                {
                    string input = new string(Encoding.ASCII.GetChars(buffer).Where(c => c != 0).ToArray());
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("checkStandrardInputOnce(): " + input);
                    Console.ForegroundColor = ConsoleColor.Gray;
                    stream.EndRead(a); // terminer la lecture
                }, null);
            }
    
            static void checkStandrardInputForever()
            {
                while (true)
                {
                    var buffer = new byte[bufferSize];
                    var stream = Console.OpenStandardInput();
    
                    stream.BeginRead(buffer, 0, buffer.Length, a =>
                    {
                        string input = new string(Encoding.ASCII.GetChars(buffer).Where(c => c != 0).ToArray());
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("checkStandrardInputForever(): " + input);
                        Console.ForegroundColor = ConsoleColor.Gray;
                        stream.EndRead(a); // terminer la lecture
                    }, null);
    
                    Thread.Sleep(500);
                }
            }
        }
    }
    


    My blog

    Whether you’re a construction worker, a forum moderator, or just someone that likes helping people. I think these guidelines can be helpful in keeping you helpful when being helpful.

    jeudi 26 avril 2012 19:03
    Auteur de réponse

Toutes les réponses

  • Comment peut-on faire alors pour détecter si l'entrée standard contient des données sans que la console ne reprenne la main pour attendre une saisie ?

    Essayez ça:

    var buffer = new byte[1024]; // lecture via un buffer en mode asynchrone
    var stream = Console.OpenStandardInput();
    stream.BeginRead(buffer, 0, buffer.Length, a => {
        //...
    }, null);
    


    My blog

    Whether you’re a construction worker, a forum moderator, or just someone that likes helping people. I think these guidelines can be helpful in keeping you helpful when being helpful.


    • Modifié Link.frEditor mercredi 25 avril 2012 16:38 Ajout de commentaire
    mercredi 25 avril 2012 16:34
    Auteur de réponse
  • Voici une autre solution qui permet de copier l'entrée standard du processus vers un fichier de log:

    using System;
    using System.IO;
    
    namespace ConsoleApplicationTest
    {
        class Program
        {
            const int bufferSize = 1024;
    
            static void Main(string[] args)
            {
                using (var stdin = Console.OpenStandardInput())
                using (var log = File.Create(@"log.txt"))
                {
                    var buffer = new byte[bufferSize];
                    int bytes;
                    while ((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        log.Write(buffer, 0, bytes);
                        log.Flush();
                    }
                }
    
            }
        }
    }
    


    My blog

    Whether you’re a construction worker, a forum moderator, or just someone that likes helping people. I think these guidelines can be helpful in keeping you helpful when being helpful.

    mercredi 25 avril 2012 17:58
    Auteur de réponse
  • Salut !

    Merci pour ces éléments, je vais les mettre en œuvre immédiatement et je te communiquerai le résultat.

    Ceci dit, la taille fixe du buffer de lecture pourrait-être problématique dans mon cas : je peux avoir à traiter de gros morceaux de données.

    En tous cas, merci, et je reposte dans l'après-midi sur le sujet...

    EuG

    jeudi 26 avril 2012 11:32
  • Alors, j'ai implémenté ça de cette manière :

            /// <summary>
            /// Lit l'entrée standard
            /// </summary>
            /// <returns>Le contenu de l'entrée standard</returns>
            private static string checkStandrardInput()
            {
                var buffer = new byte[1024];                
                var stream = Console.OpenStandardInput();
    
                if (!stream.CanRead)
                    return string.Empty;
    
                bool reading = true;
    
                stream.BeginRead(buffer, 0, buffer.Length, a =>
                {
                    reading = false;
                }, null);
    
                while (reading)
                    continue;
    
                return new string(System.Text.Encoding.ASCII.GetChars(buffer));            
            }

    Et j'appelle cette méthode dans mon programme lorsque je veux lire l'entrée standard.

    Résultat : Ca ne change rien : quand il n y a rien sur l'entrée standard, la console reprend la main.

    De plus, j'ai un problème d'encodage associé au passage par un tableau d'octets, quelque soit l'encoding que j'utilise (ASCII, Default, Unicode, UTF8, 7 et 32...)

    Est-ce que tu l'aurais implémenté de cette manière toi ?

    Merci d'avance !

    EuG

    [UPDATE] : J'ai aussi essayé ta méthode qui écrit le contenu de l'entrée standard dans un fichier : même problème, si l'entrée standard est vide, la console s'affiche et attend une saisie manuelle...


    • Modifié EugeneMoulin jeudi 26 avril 2012 12:44 Test du fichier en plus
    jeudi 26 avril 2012 11:57
  • Je l'écrirait plutôt comme ça:

    using System;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace ConsoleApplicationTest
    {
        class Program
        {
            const int bufferSize = 1024;
    
            static void Main(string[] args)
            {
                Console.WriteLine("\nTapez et retapez n'importe quoi puis appuyez sur la touche Entrée:");
                new Thread(new ThreadStart(checkStandrardInputOnce)).Start(); // Lancer la première capture
                Thread.Sleep(1000); // attendre un peu
                new Thread(new ThreadStart(checkStandrardInputForever)).Start(); // Lancer la deuxième capture
            }
    
            static void checkStandrardInputOnce()
            {
                var buffer = new byte[bufferSize];
                var stream = Console.OpenStandardInput();
    
                stream.BeginRead(buffer, 0, buffer.Length, a =>
                {
                    string input = new string(Encoding.ASCII.GetChars(buffer).Where(c => c != 0).ToArray());
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("checkStandrardInputOnce(): " + input);
                    Console.ForegroundColor = ConsoleColor.Gray;
                    stream.EndRead(a); // terminer la lecture
                }, null);
            }
    
            static void checkStandrardInputForever()
            {
                while (true)
                {
                    var buffer = new byte[bufferSize];
                    var stream = Console.OpenStandardInput();
    
                    stream.BeginRead(buffer, 0, buffer.Length, a =>
                    {
                        string input = new string(Encoding.ASCII.GetChars(buffer).Where(c => c != 0).ToArray());
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("checkStandrardInputForever(): " + input);
                        Console.ForegroundColor = ConsoleColor.Gray;
                        stream.EndRead(a); // terminer la lecture
                    }, null);
    
                    Thread.Sleep(500);
                }
            }
        }
    }
    


    My blog

    Whether you’re a construction worker, a forum moderator, or just someone that likes helping people. I think these guidelines can be helpful in keeping you helpful when being helpful.

    jeudi 26 avril 2012 19:03
    Auteur de réponse
  • Salut,

    Merci beaucoup, je comprends mieux comme ça.

    J'ai fait tourner ton code dans une application de test, tout est nickel sauf les caractères accentués.

    Maintenant, je vais essayer de l'adapter à mon cas et de résoudre cette histoire d'accents.

    Je te donne le résultat de mes essais un peu plus tard.

    Encore Merci !

    EuG

    vendredi 27 avril 2012 08:28
  • Alors, j'ai utilisé cette approche dans mon cas.

    Cela pourrait fonctionner sauf que ta solution ne peut pas s'utiliser en synchrone.

    Dans la méthode Main, au niveau de mon programme, je souhaite ne pas attendre que l'utilisateur clique sur entrée, j'ai donc essayé d'appeller checkStandardInputOnce dans le main thread, mais le comportement indésirable revient : la console reprend la main.

    Ceci dit, je n'ai pas eu beaucoup de temps à passer sur ce travail aujourd'hui, je pense y retravailler ce week-end, toujours en creusant dans le sens de la solution que tu proposes, je te tiendrais au courant dans mon avancement.

    Merci beaucoup pour ton aide.

    Ah ! Et je t'ai ajouté un point helpful pour ta réponse parce que même si elle n'est pas forcément parfaite dans mon cas particulier, c'est une excellente source d'information sur la manière de lire les entrées de la console.

    vendredi 27 avril 2012 14:11